Commit | Line | Data |
---|---|---|
8c8bf09f | 1 | /******************************************************************************* |
bbc1c411 | 2 | * Copyright (c) 2009, 2012 Ericsson |
306dc902 | 3 | * |
cbbcc354 | 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 | |
8c8bf09f ASL |
6 | * accompanies this distribution, and is available at |
7 | * http://www.eclipse.org/legal/epl-v10.html | |
306dc902 | 8 | * |
8c8bf09f | 9 | * Contributors: |
1f506a43 | 10 | * Francois Chouinard - Initial API and implementation |
bbc1c411 | 11 | * Francois Chouinard - Updated as per TMF Event Model 1.0 |
8c8bf09f ASL |
12 | *******************************************************************************/ |
13 | ||
6c13869b | 14 | package org.eclipse.linuxtools.tmf.core.event; |
8c8bf09f | 15 | |
ea2b103b | 16 | import java.util.Arrays; |
4c564a2d FC |
17 | import java.util.HashMap; |
18 | import java.util.Map; | |
19 | ||
8c8bf09f | 20 | /** |
b9e37ffd | 21 | * A basic implementation of ITmfEventField. |
8c8bf09f | 22 | * <p> |
b9e37ffd FC |
23 | * Non-value fields are structural (i.e. used to represent the event structure |
24 | * including optional fields) while the valued fields are actual event fields. | |
306dc902 | 25 | * |
b9e37ffd FC |
26 | * @version 1.0 |
27 | * @author Francois Chouinard | |
306dc902 | 28 | * |
b9e37ffd | 29 | * @see ITmfEvent |
f7703ed6 | 30 | * @see ITmfEventType |
8c8bf09f | 31 | */ |
0316808c | 32 | public class TmfEventField implements ITmfEventField, Cloneable { |
8c8bf09f | 33 | |
cbd4ad82 | 34 | // ------------------------------------------------------------------------ |
8c8bf09f | 35 | // Attributes |
cbd4ad82 | 36 | // ------------------------------------------------------------------------ |
8c8bf09f | 37 | |
4c564a2d FC |
38 | private String fName; |
39 | private Object fValue; | |
40 | private ITmfEventField[] fFields; | |
8c8bf09f | 41 | |
4c564a2d FC |
42 | private String[] fFieldNames; |
43 | private Map<String, ITmfEventField> fNameMapping; | |
085d898f | 44 | |
cbd4ad82 | 45 | // ------------------------------------------------------------------------ |
8c8bf09f | 46 | // Constructors |
cbd4ad82 FC |
47 | // ------------------------------------------------------------------------ |
48 | ||
cbbcc354 | 49 | /** |
50 | * Default constructor | |
51 | */ | |
cbd4ad82 | 52 | @SuppressWarnings("unused") |
cbbcc354 | 53 | private TmfEventField() { |
cbd4ad82 | 54 | } |
8c8bf09f | 55 | |
4c564a2d | 56 | /** |
75d42a16 | 57 | * Constructor for a structural field |
306dc902 | 58 | * |
4c564a2d | 59 | * @param name the event field id |
0d9a6d76 | 60 | * @param fields the list of subfields |
4c564a2d | 61 | */ |
085d898f | 62 | public TmfEventField(final String name, final ITmfEventField[] fields) { |
75d42a16 | 63 | this(name, null, fields); |
4c564a2d FC |
64 | } |
65 | ||
66 | /** | |
f7703ed6 | 67 | * Constructor for a terminal field (no subfields) |
306dc902 | 68 | * |
4c564a2d | 69 | * @param name the event field id |
75d42a16 | 70 | * @param value the event field value |
4c564a2d | 71 | */ |
085d898f | 72 | public TmfEventField(final String name, final Object value) { |
75d42a16 | 73 | this(name, value, null); |
4c564a2d FC |
74 | } |
75 | ||
8c8bf09f | 76 | /** |
cbbcc354 | 77 | * Full constructor |
306dc902 | 78 | * |
4c564a2d | 79 | * @param name the event field id |
cbbcc354 | 80 | * @param value the event field value |
0d9a6d76 | 81 | * @param fields the list of subfields |
8c8bf09f | 82 | */ |
085d898f | 83 | public TmfEventField(final String name, final Object value, final ITmfEventField[] fields) { |
b9e37ffd | 84 | if (name == null) { |
cbbcc354 | 85 | throw new IllegalArgumentException(); |
b9e37ffd | 86 | } |
4c564a2d | 87 | fName = name; |
cbbcc354 | 88 | fValue = value; |
ea2b103b | 89 | fFields = (fields != null) ? Arrays.copyOf(fields, fields.length) : null; |
4c564a2d | 90 | populateStructs(); |
28b94d61 FC |
91 | } |
92 | ||
93 | /** | |
cbbcc354 | 94 | * Copy constructor |
306dc902 | 95 | * |
cbbcc354 | 96 | * @param field the other event field |
28b94d61 | 97 | */ |
085d898f | 98 | public TmfEventField(final TmfEventField field) { |
b9e37ffd | 99 | if (field == null) { |
085d898f | 100 | throw new IllegalArgumentException(); |
b9e37ffd | 101 | } |
085d898f FC |
102 | fName = field.fName; |
103 | fValue = field.fValue; | |
104 | fFields = field.fFields; | |
105 | fFieldNames = field.fFieldNames; | |
75d42a16 | 106 | populateStructs(); |
28b94d61 FC |
107 | } |
108 | ||
cbd4ad82 | 109 | // ------------------------------------------------------------------------ |
cbbcc354 | 110 | // ITmfEventField |
cbd4ad82 | 111 | // ------------------------------------------------------------------------ |
8c8bf09f | 112 | |
d7dbf09a FC |
113 | /* (non-Javadoc) |
114 | * @see org.eclipse.linuxtools.tmf.core.event.ITmfEventField#getName() | |
115 | */ | |
116 | @Override | |
4c564a2d FC |
117 | public String getName() { |
118 | return fName; | |
28b94d61 FC |
119 | } |
120 | ||
d7dbf09a FC |
121 | /* (non-Javadoc) |
122 | * @see org.eclipse.linuxtools.tmf.core.event.ITmfEventField#getValue() | |
123 | */ | |
124 | @Override | |
8c8bf09f ASL |
125 | public Object getValue() { |
126 | return fValue; | |
127 | } | |
128 | ||
d7dbf09a FC |
129 | /* (non-Javadoc) |
130 | * @see org.eclipse.linuxtools.tmf.core.event.ITmfEventField#getFieldNames() | |
131 | */ | |
132 | @Override | |
4c564a2d | 133 | public String[] getFieldNames() { |
ea2b103b | 134 | return Arrays.copyOf(fFieldNames, fFieldNames.length); |
4c564a2d FC |
135 | } |
136 | ||
d7dbf09a FC |
137 | /* (non-Javadoc) |
138 | * @see org.eclipse.linuxtools.tmf.core.event.ITmfEventField#getFieldName(int) | |
139 | */ | |
140 | @Override | |
085d898f FC |
141 | public String getFieldName(final int index) { |
142 | final ITmfEventField field = getField(index); | |
b9e37ffd | 143 | if (field != null) { |
4c564a2d | 144 | return field.getName(); |
b9e37ffd | 145 | } |
4c564a2d FC |
146 | return null; |
147 | } | |
148 | ||
d7dbf09a FC |
149 | /* (non-Javadoc) |
150 | * @see org.eclipse.linuxtools.tmf.core.event.ITmfEventField#getFields() | |
151 | */ | |
152 | @Override | |
4c564a2d | 153 | public ITmfEventField[] getFields() { |
8b63ffb9 | 154 | return (fFields != null) ? Arrays.copyOf(fFields, fFields.length) : new ITmfEventField[0]; |
4c564a2d FC |
155 | } |
156 | ||
d7dbf09a FC |
157 | /* (non-Javadoc) |
158 | * @see org.eclipse.linuxtools.tmf.core.event.ITmfEventField#getField(java.lang.String) | |
159 | */ | |
160 | @Override | |
085d898f | 161 | public ITmfEventField getField(final String name) { |
4c564a2d FC |
162 | return fNameMapping.get(name); |
163 | } | |
164 | ||
d7dbf09a FC |
165 | /* (non-Javadoc) |
166 | * @see org.eclipse.linuxtools.tmf.core.event.ITmfEventField#getField(int) | |
167 | */ | |
168 | @Override | |
085d898f | 169 | public ITmfEventField getField(final int index) { |
b9e37ffd | 170 | if (fFields != null && index >= 0 && index < fFields.length) { |
4c564a2d | 171 | return fFields[index]; |
b9e37ffd | 172 | } |
4c564a2d | 173 | return null; |
cbbcc354 | 174 | } |
175 | ||
176 | // ------------------------------------------------------------------------ | |
177 | // Convenience setters | |
178 | // ------------------------------------------------------------------------ | |
179 | ||
28b94d61 | 180 | /** |
4c564a2d FC |
181 | * @param value new field raw value |
182 | * @param fields the corresponding fields | |
28b94d61 | 183 | */ |
085d898f | 184 | protected void setValue(final Object value, final ITmfEventField[] fields) { |
28b94d61 | 185 | fValue = value; |
beae214a | 186 | fFields = (fields != null) ? Arrays.copyOf(fields, fields.length) : null; |
4c564a2d FC |
187 | populateStructs(); |
188 | } | |
189 | ||
190 | // ------------------------------------------------------------------------ | |
191 | // Operations | |
192 | // ------------------------------------------------------------------------ | |
193 | ||
194 | /** | |
195 | * Create a root field from a list of labels. | |
306dc902 | 196 | * |
4c564a2d FC |
197 | * @param labels the list of labels |
198 | * @return the (flat) root list | |
199 | */ | |
085d898f FC |
200 | public final static ITmfEventField makeRoot(final String[] labels) { |
201 | final ITmfEventField[] fields = new ITmfEventField[labels.length]; | |
b9e37ffd | 202 | for (int i = 0; i < labels.length; i++) { |
4c564a2d | 203 | fields[i] = new TmfEventField(labels[i], null); |
b9e37ffd FC |
204 | } |
205 | // Return a new root field; | |
206 | return new TmfEventField(ITmfEventField.ROOT_FIELD_ID, fields); | |
4c564a2d FC |
207 | } |
208 | ||
209 | /* | |
210 | * Populate the subfield names and the name map | |
211 | */ | |
212 | private void populateStructs() { | |
085d898f | 213 | final int nbFields = (fFields != null) ? fFields.length : 0; |
4c564a2d FC |
214 | fFieldNames = new String[nbFields]; |
215 | fNameMapping = new HashMap<String, ITmfEventField>(); | |
216 | for (int i = 0; i < nbFields; i++) { | |
085d898f | 217 | final String name = fFields[i].getName(); |
4c564a2d FC |
218 | fFieldNames[i] = name; |
219 | fNameMapping.put(name, fFields[i]); | |
220 | } | |
28b94d61 FC |
221 | } |
222 | ||
cbbcc354 | 223 | // ------------------------------------------------------------------------ |
224 | // Cloneable | |
225 | // ------------------------------------------------------------------------ | |
226 | ||
d7dbf09a FC |
227 | /* (non-Javadoc) |
228 | * @see java.lang.Object#clone() | |
229 | */ | |
cbbcc354 | 230 | @Override |
8c149234 | 231 | public TmfEventField clone() { |
cbbcc354 | 232 | TmfEventField clone = null; |
233 | try { | |
234 | clone = (TmfEventField) super.clone(); | |
4c564a2d | 235 | clone.fName = fName; |
cbbcc354 | 236 | clone.fValue = fValue; |
4c564a2d FC |
237 | clone.fFields = (fFields != null) ? fFields.clone() : null; |
238 | clone.populateStructs(); | |
085d898f | 239 | } catch (final CloneNotSupportedException e) { |
cbbcc354 | 240 | } |
241 | return clone; | |
242 | } | |
243 | ||
cbd4ad82 FC |
244 | // ------------------------------------------------------------------------ |
245 | // Object | |
246 | // ------------------------------------------------------------------------ | |
8c8bf09f | 247 | |
d7dbf09a FC |
248 | /* (non-Javadoc) |
249 | * @see java.lang.Object#hashCode() | |
250 | */ | |
28b94d61 | 251 | @Override |
cbd4ad82 | 252 | public int hashCode() { |
cbbcc354 | 253 | final int prime = 31; |
254 | int result = 1; | |
75d42a16 | 255 | result = prime * result + fName.hashCode(); |
cbbcc354 | 256 | result = prime * result + ((fValue == null) ? 0 : fValue.hashCode()); |
2fb2eb37 | 257 | return result; |
cbd4ad82 FC |
258 | } |
259 | ||
d7dbf09a FC |
260 | /* (non-Javadoc) |
261 | * @see java.lang.Object#equals(java.lang.Object) | |
262 | */ | |
cbbcc354 | 263 | @Override |
085d898f | 264 | public boolean equals(final Object obj) { |
b9e37ffd | 265 | if (this == obj) { |
cbbcc354 | 266 | return true; |
b9e37ffd FC |
267 | } |
268 | if (obj == null) { | |
cbbcc354 | 269 | return false; |
b9e37ffd FC |
270 | } |
271 | if (!(obj instanceof TmfEventField)) { | |
cbbcc354 | 272 | return false; |
b9e37ffd | 273 | } |
085d898f | 274 | final TmfEventField other = (TmfEventField) obj; |
b9e37ffd | 275 | if (!fName.equals(other.fName)) { |
cbbcc354 | 276 | return false; |
b9e37ffd | 277 | } |
cbbcc354 | 278 | if (fValue == null) { |
b9e37ffd | 279 | if (other.fValue != null) { |
cbbcc354 | 280 | return false; |
b9e37ffd FC |
281 | } |
282 | } else if (!fValue.equals(other.fValue)) { | |
cbbcc354 | 283 | return false; |
b9e37ffd | 284 | } |
cbbcc354 | 285 | return true; |
28b94d61 FC |
286 | } |
287 | ||
d7dbf09a FC |
288 | /* (non-Javadoc) |
289 | * @see java.lang.Object#toString() | |
290 | */ | |
82b08e62 | 291 | @Override |
cbbcc354 | 292 | public String toString() { |
306dc902 AM |
293 | StringBuilder ret = new StringBuilder(); |
294 | if (fName.equals(ITmfEventField.ROOT_FIELD_ID)) { | |
295 | /* | |
296 | * If this field is a top-level "field container", we will print its | |
297 | * sub-fields directly. | |
298 | */ | |
299 | appendSubFields(ret); | |
300 | ||
301 | } else { | |
302 | /* The field has its own values */ | |
303 | ret.append(fName); | |
304 | ret.append('='); | |
305 | ret.append(fValue); | |
306 | ||
307 | if (fFields != null && fFields.length > 0) { | |
308 | /* | |
309 | * In addition to its own name/value, this field also has | |
310 | * sub-fields. | |
311 | */ | |
312 | ret.append(" ["); //$NON-NLS-1$ | |
313 | appendSubFields(ret); | |
314 | ret.append(']'); | |
315 | } | |
316 | } | |
317 | return ret.toString(); | |
318 | } | |
319 | ||
320 | private void appendSubFields(StringBuilder sb) { | |
321 | ITmfEventField field; | |
322 | for (int i = 0; i < getFields().length; i++) { | |
323 | field = getFields()[i]; | |
324 | if (i != 0) { | |
325 | sb.append(", ");//$NON-NLS-1$ | |
326 | } | |
327 | sb.append(field.toString()); | |
328 | } | |
8c8bf09f | 329 | } |
1f506a43 | 330 | |
cbbcc354 | 331 | } |