1 /*******************************************************************************
2 * Copyright (c) 2011, 2014 Ericsson, Ecole Polytechnique de Montreal and others
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
9 * Contributors: Matthew Khouzam - Initial API and implementation
10 * Contributors: Simon Marchi - Initial API and implementation
11 *******************************************************************************/
13 package org
.eclipse
.tracecompass
.ctf
.core
.event
.types
;
15 import java
.util
.Collections
;
16 import java
.util
.LinkedList
;
17 import java
.util
.List
;
20 import org
.eclipse
.jdt
.annotation
.NonNull
;
21 import org
.eclipse
.tracecompass
.ctf
.core
.event
.scope
.IDefinitionScope
;
22 import org
.eclipse
.tracecompass
.ctf
.core
.event
.scope
.ILexicalScope
;
23 import org
.eclipse
.tracecompass
.ctf
.core
.event
.types
.StructDeclaration
.InternalDef
;
25 import com
.google
.common
.base
.Joiner
;
26 import com
.google
.common
.collect
.ImmutableList
;
27 import com
.google
.common
.collect
.ImmutableMap
;
28 import com
.google
.common
.collect
.ImmutableMap
.Builder
;
31 * A CTF structure definition (similar to a C structure).
33 * A structure is similar to a C structure, it is a compound data type that
34 * contains other datatypes in fields. they are stored in an hashmap and indexed
35 * by names which are strings.
37 * TODO: move me to internal
40 * @author Matthew Khouzam
41 * @author Simon Marchi
43 public final class StructDefinition
extends ScopedDefinition
implements ICompositeDefinition
{
45 // ------------------------------------------------------------------------
47 // ------------------------------------------------------------------------
49 private final @NonNull List
<@NonNull String
> fFieldNames
;
50 private final Definition
[] fDefinitions
;
51 private Map
<String
, Definition
> fDefinitionsMap
= null;
53 // ------------------------------------------------------------------------
55 // ------------------------------------------------------------------------
61 * the parent declaration
62 * @param definitionScope
64 * @param structFieldName
70 public StructDefinition(@NonNull StructDeclaration declaration
,
71 IDefinitionScope definitionScope
,
72 @NonNull String structFieldName
,
73 Definition
[] definitions
) {
74 super(declaration
, definitionScope
, structFieldName
);
75 fFieldNames
= ImmutableList
.copyOf(declaration
.getFieldsList());
76 fDefinitions
= definitions
;
77 if (fFieldNames
.isEmpty()) {
78 fDefinitionsMap
= Collections
.EMPTY_MAP
;
83 * Constructor This one takes the scope and thus speeds up definition
87 * the parent declaration
88 * @param definitionScope
91 * the scope of this variable
92 * @param structFieldName
100 public StructDefinition(@NonNull StructDeclaration declaration
,
101 IDefinitionScope definitionScope
,
102 @NonNull ILexicalScope scope
,
103 @NonNull String structFieldName
,
104 @NonNull Iterable
<@NonNull String
> fieldNames
,
105 Definition
[] definitions
) {
106 super(declaration
, definitionScope
, structFieldName
, scope
);
107 fFieldNames
= ImmutableList
.copyOf(fieldNames
);
108 fDefinitions
= definitions
;
109 if (fFieldNames
.isEmpty()) {
110 fDefinitionsMap
= Collections
.EMPTY_MAP
;
114 // ------------------------------------------------------------------------
115 // Getters/Setters/Predicates
116 // ------------------------------------------------------------------------
119 public Definition
getDefinition(String fieldName
) {
120 if (fDefinitionsMap
== null) {
121 /* Build the definitions map */
122 Builder
<String
, Definition
> mapBuilder
= new ImmutableMap
.Builder
<>();
123 for (int i
= 0; i
< fFieldNames
.size(); i
++) {
124 if (fDefinitions
[i
] != null) {
125 mapBuilder
.put(fFieldNames
.get(i
), fDefinitions
[i
]);
128 fDefinitionsMap
= mapBuilder
.build();
130 return fDefinitionsMap
.get(fieldName
);
134 public @NonNull List
<@NonNull String
> getFieldNames() {
139 public StructDeclaration
getDeclaration() {
140 return (StructDeclaration
) super.getDeclaration();
143 // ------------------------------------------------------------------------
145 // ------------------------------------------------------------------------
148 public Definition
lookupDefinition(String lookupPath
) {
149 return lookupDefinition(lookupPath
, null);
153 public String
toString() {
154 StringBuilder builder
= new StringBuilder();
156 builder
.append("{ "); //$NON-NLS-1$
158 List
<String
> fields
= new LinkedList
<>();
159 for (String field
: fFieldNames
) {
160 String appendee
= field
+ " = " + lookupDefinition(field
).toString(); //$NON-NLS-1$
161 fields
.add(appendee
);
163 Joiner joiner
= Joiner
.on(", ").skipNulls(); //$NON-NLS-1$
164 builder
.append(joiner
.join(fields
));
166 builder
.append(" }"); //$NON-NLS-1$
168 return builder
.toString();
172 * Lookup definition while exclusing the caller
176 * @param defintionToExclude
177 * the definition to exclude, can be null
178 * @return the definition or null
181 public Definition
lookupDefinition(String lookupPath
, ScopedDefinition defintionToExclude
) {
183 * The fields are created in order of appearance, so if a variant or
184 * sequence refers to a field that is after it, the field's definition
185 * will not be there yet in the hashmap.
187 int val
= fFieldNames
.indexOf(lookupPath
);
189 return fDefinitions
[val
];
191 String lookupUnderscored
= "_" + lookupPath
; //$NON-NLS-1$
192 val
= fFieldNames
.indexOf(lookupUnderscored
);
194 return fDefinitions
[val
];
196 for (IDefinition child
: fDefinitions
) {
197 if (child
instanceof ScopedDefinition
) {
198 if (!child
.equals(defintionToExclude
)) {
199 IDefinition def
= ((ScopedDefinition
) child
).lookupDefinition(lookupPath
);
200 if (def
instanceof Definition
) {
201 return (Definition
) def
;
206 if (getDefinitionScope() instanceof InternalDef
) {
207 return (Definition
) ((InternalDef
) getDefinitionScope()).lookupDefinitionBreakLoop(lookupPath
);
209 return (Definition
) getDefinitionScope().lookupDefinition(lookupPath
);