1 /*
2  * Copyright (C) 2017 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 import java.util.Objects;
20 
21 /**
22  * Used by the DiffedField class to return the result of diffing two
23  * collections of fields.
24  */
25 public class DiffedFieldValue {
26   /**
27    * The name of the field.
28    */
29   public final String name;
30 
31   /**
32    * The type of the field.
33    */
34   public final Type type;
35 
36   /**
37    * The value of the field in the current heap dump.
38    */
39   public final Value current;
40 
41   /**
42    * The value of the field in the baseline heap dump.
43    */
44   public final Value baseline;
45 
46   /**
47    * Whether the field was added to, deleted from, or matched with a field in
48    * the baseline heap dump.
49    */
50   public final Status status;
51 
52   /**
53    * A status enum to indicate whether a field was added to, deleted from, or
54    * matched with a field in the baseline heap dump.
55    */
56   public static enum Status {
57     /**
58      * The field exists in the current heap dump but not the baseline.
59      */
60     ADDED,
61 
62     /**
63      * The field exists in both the current and baseline heap dumps.
64      */
65     MATCHED,
66 
67     /**
68      * The field exists in the baseline heap dump but not the current.
69      */
70     DELETED
71   };
72 
73   /**
74    * Constructs a DiffedFieldValue where there are both current and baseline
75    * fields.
76    *
77    * @param current the current field
78    * @param baseline the baseline field
79    * @return the constructed DiffedFieldValue
80    */
matched(FieldValue current, FieldValue baseline)81   public static DiffedFieldValue matched(FieldValue current, FieldValue baseline) {
82     return new DiffedFieldValue(current.name,
83                                 current.type,
84                                 current.value,
85                                 baseline.value,
86                                 Status.MATCHED);
87   }
88 
89   /**
90    * Constructs a DiffedFieldValue where there is no baseline field.
91    *
92    * @param current the current field
93    * @return the constructed DiffedFieldValue
94    */
added(FieldValue current)95   public static DiffedFieldValue added(FieldValue current) {
96     return new DiffedFieldValue(current.name, current.type, current.value, null, Status.ADDED);
97   }
98 
99   /**
100    * Constructs a DiffedFieldValue where there is no current field.
101    *
102    * @param baseline the baseline field
103    * @return the constructed DiffedFieldValue
104    */
deleted(FieldValue baseline)105   public static DiffedFieldValue deleted(FieldValue baseline) {
106     return new DiffedFieldValue(baseline.name, baseline.type, null, baseline.value, Status.DELETED);
107   }
108 
DiffedFieldValue(String name, Type type, Value current, Value baseline, Status status)109   private DiffedFieldValue(String name, Type type, Value current, Value baseline, Status status) {
110     this.name = name;
111     this.type = type;
112     this.current = current;
113     this.baseline = baseline;
114     this.status = status;
115   }
116 
hashCode()117   @Override public int hashCode() {
118     return Objects.hash(name, type, current, baseline, status);
119   }
120 
121   @Override
equals(Object otherObject)122   public boolean equals(Object otherObject) {
123     if (otherObject instanceof DiffedFieldValue) {
124       DiffedFieldValue other = (DiffedFieldValue)otherObject;
125       return name.equals(other.name)
126         && type.equals(other.type)
127         && Objects.equals(current, other.current)
128         && Objects.equals(baseline, other.baseline)
129         && Objects.equals(status, other.status);
130     }
131     return false;
132   }
133 
134   @Override
toString()135   public String toString() {
136     switch (status) {
137       case ADDED:
138         return "(" + name + " " + type + " +" + current + ")";
139 
140       case MATCHED:
141         return "(" + name + " " + type + " " + current + " " + baseline + ")";
142 
143       case DELETED:
144         return "(" + name + " " + type + " -" + baseline + ")";
145 
146       default:
147         // There are no other members.
148         throw new AssertionError("unsupported enum member");
149     }
150   }
151 }
152