ctf: add isBinaryEquivalent() to IDeclaration
[deliverable/tracecompass.git] / org.eclipse.tracecompass.ctf.core / src / org / eclipse / tracecompass / ctf / core / event / types / VariantDeclaration.java
1 /*******************************************************************************
2 * Copyright (c) 2011, 2014 Ericsson, Ecole Polytechnique de Montreal and others
3 *
4 * All rights reserved. This program and the accompanying materials are made
5 * available under the terms of the Eclipse Public License v1.0 which
6 * accompanies this distribution, and is available at
7 * http://www.eclipse.org/legal/epl-v10.html
8 *
9 * Contributors: Matthew Khouzam - Initial API and implementation
10 * Contributors: Simon Marchi - Initial API and implementation
11 *******************************************************************************/
12
13 package org.eclipse.tracecompass.ctf.core.event.types;
14
15 import java.util.Collection;
16 import java.util.Collections;
17 import java.util.HashMap;
18 import java.util.Map;
19 import java.util.Map.Entry;
20
21 import org.eclipse.tracecompass.ctf.core.event.io.BitBuffer;
22 import org.eclipse.tracecompass.ctf.core.event.scope.IDefinitionScope;
23 import org.eclipse.tracecompass.ctf.core.trace.CTFReaderException;
24
25 /**
26 * A CTFC variant declaration.
27 *
28 * A variant is similar to a C union, only taking the minimum size of the types,
29 * it is a compound data type that contains other datatypes in fields. they are
30 * stored in an hashmap and indexed by names which are strings.
31 *
32 * @version 1.0
33 * @author Matthew Khouzam
34 * @author Simon Marchi
35 */
36 public class VariantDeclaration extends Declaration {
37
38 // ------------------------------------------------------------------------
39 // Attributes
40 // ------------------------------------------------------------------------
41
42 private String fTag = null;
43 private static final long ALIGNMENT = 1;
44 private final Map<String, IDeclaration> fFields = Collections.synchronizedMap(new HashMap<String, IDeclaration>());
45 private EnumDefinition fTagDef;
46 private IDeclaration fDeclarationToPopulate;
47 private IDefinitionScope fPrevDefinitionScope;
48
49 // ------------------------------------------------------------------------
50 // Constructors
51 // ------------------------------------------------------------------------
52
53 /**
54 * Constructor
55 */
56 public VariantDeclaration() {
57 }
58
59 // ------------------------------------------------------------------------
60 // Getters/Setters/Predicates
61 // ------------------------------------------------------------------------
62
63 /**
64 * @return Does the variant have a tag
65 */
66 public boolean isTagged() {
67 return fTag != null;
68 }
69
70 /**
71 * Lookup if a field exists in the variant
72 *
73 * @param fieldTag
74 * the field tag name
75 * @return true = field tag exists
76 */
77 public boolean hasField(String fieldTag) {
78 return fFields.containsKey(fieldTag);
79 }
80
81 /**
82 * Sets the tag in a variant
83 *
84 * @param tag
85 * the tag
86 */
87 public void setTag(String tag) {
88 fTag = tag;
89 fTagDef = null;
90 }
91
92 /**
93 * Gets current variant tag
94 *
95 * @return the variant tag.
96 */
97 public String getTag() {
98 return fTag;
99 }
100
101 /**
102 * Gets the fields of the variant
103 *
104 * @return the fields of the variant
105 * @since 2.0
106 */
107 public Map<String, IDeclaration> getFields() {
108 return this.fFields;
109 }
110
111 @Override
112 public long getAlignment() {
113 return ALIGNMENT;
114 }
115
116 // ------------------------------------------------------------------------
117 // Operations
118 // ------------------------------------------------------------------------
119
120 /**
121 * @since 3.0
122 */
123 @Override
124 public VariantDefinition createDefinition(IDefinitionScope definitionScope,
125 String fieldName, BitBuffer input) throws CTFReaderException {
126 alignRead(input);
127 if (fPrevDefinitionScope != definitionScope) {
128 fTagDef = null;
129 fPrevDefinitionScope = definitionScope;
130 }
131 EnumDefinition tagDef = fTagDef;
132 if (tagDef == null) {
133 Definition def = definitionScope.lookupDefinition(fTag);
134 tagDef = (EnumDefinition) ((def instanceof EnumDefinition) ? def : null);
135 }
136 if (tagDef == null) {
137 throw new CTFReaderException("Tag is not defined " + fTag); //$NON-NLS-1$
138 }
139 String varFieldName = tagDef.getStringValue();
140 fDeclarationToPopulate = fFields.get(varFieldName);
141 if (fDeclarationToPopulate == null) {
142 throw new CTFReaderException("Unknown enum selector for variant " + //$NON-NLS-1$
143 definitionScope.getScopePath().toString());
144 }
145 Definition fieldValue = fDeclarationToPopulate.createDefinition(definitionScope, fieldName, input);
146 return new VariantDefinition(this, definitionScope, varFieldName, fieldName, fieldValue);
147 }
148
149 /**
150 * Add a field to this CTF Variant
151 *
152 * @param fieldTag
153 * The tag of the new field
154 * @param declaration
155 * The Declaration of this new field
156 */
157 public void addField(String fieldTag, IDeclaration declaration) {
158 fFields.put(fieldTag, declaration);
159 }
160
161 /**
162 * gets the tag definition
163 *
164 * @return the fTagDef
165 * @since 3.0
166 */
167 public EnumDefinition getTagDef() {
168 return fTagDef;
169 }
170
171 /**
172 * @since 3.0
173 */
174 @Override
175 public int getMaximumSize() {
176 Collection<IDeclaration> values = fFields.values();
177 int maxSize = 0;
178 for (IDeclaration field : values) {
179 maxSize = Math.max(maxSize, field.getMaximumSize());
180 }
181 return maxSize;
182 }
183
184 @Override
185 public String toString() {
186 /* Only used for debugging */
187 StringBuilder sb = new StringBuilder();
188 sb.append("[declaration] variant["); //$NON-NLS-1$
189 for (Entry<String, IDeclaration> field : fFields.entrySet()) {
190 sb.append(field.getKey()).append(':').append(field.getValue());
191 }
192 sb.append(']');
193 return sb.toString();
194 }
195
196 @Override
197 public int hashCode() {
198 final int prime = 31;
199 int result = 1;
200 result = prime * result + ((fDeclarationToPopulate == null) ? 0 : fDeclarationToPopulate.hashCode());
201 if (fFields == null) {
202 result = prime * result;
203 } else {
204 for (Entry<String, IDeclaration> field : fFields.entrySet()) {
205 result = prime * result + field.getValue().hashCode();
206 }
207 }
208 result = prime * result + ((fPrevDefinitionScope == null) ? 0 : fPrevDefinitionScope.hashCode());
209 result = prime * result + ((fTag == null) ? 0 : fTag.hashCode());
210 result = prime * result + ((fTagDef == null) ? 0 : fTagDef.hashCode());
211 return result;
212 }
213
214 @Override
215 public boolean equals(Object obj) {
216 if (this == obj) {
217 return true;
218 }
219 if (obj == null) {
220 return false;
221 }
222 if (getClass() != obj.getClass()) {
223 return false;
224 }
225 VariantDeclaration other = (VariantDeclaration) obj;
226 if (fDeclarationToPopulate == null) {
227 if (other.fDeclarationToPopulate != null) {
228 return false;
229 }
230 } else if (!fDeclarationToPopulate.equals(other.fDeclarationToPopulate)) {
231 return false;
232 }
233 // do not check the order of the fields
234
235 if (fFields == null) {
236 if (other.fFields != null) {
237 return false;
238 }
239 } else {
240 if( !fFields.equals(other.fFields)) {
241 return false;
242 }
243 }
244 if (fPrevDefinitionScope == null) {
245 if (other.fPrevDefinitionScope != null) {
246 return false;
247 }
248 } else if (!fPrevDefinitionScope.equals(other.fPrevDefinitionScope)) {
249 return false;
250 }
251 if (fTag == null) {
252 if (other.fTag != null) {
253 return false;
254 }
255 } else if (!fTag.equals(other.fTag)) {
256 return false;
257 }
258 if (fTagDef == null) {
259 if (other.fTagDef != null) {
260 return false;
261 }
262 } else if (!fTagDef.equals(other.fTagDef)) {
263 return false;
264 }
265 return true;
266 }
267
268 @Override
269 public boolean isBinaryEquivalent(IDeclaration obj) {
270 if (this == obj) {
271 return true;
272 }
273 if (obj == null) {
274 return false;
275 }
276 if (getClass() != obj.getClass()) {
277 return false;
278 }
279 VariantDeclaration other = (VariantDeclaration) obj;
280 if (fFields == null) {
281 if (other.fFields != null) {
282 return false;
283 }
284 } else {
285 if (fFields.size() != other.fFields.size()) {
286 return false;
287 }
288 for (Entry<String, IDeclaration> field : fFields.entrySet()) {
289 if (!other.fFields.containsKey(field.getKey())) {
290 return false;
291 }
292 IDeclaration field2 = other.fFields.get(field.getKey());
293 if (!field2.isBinaryEquivalent(field.getValue())) {
294 return false;
295 }
296 }
297 }
298 return true;
299 }
300
301 }
This page took 0.043017 seconds and 5 git commands to generate.