tmf: Move plugins to their own sub-directory
[deliverable/tracecompass.git] / tmf / org.eclipse.tracecompass.tmf.core / src / org / eclipse / tracecompass / tmf / core / event / TmfEventField.java
1 /*******************************************************************************
2 * Copyright (c) 2009, 2015 Ericsson
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:
10 * Francois Chouinard - Initial API and implementation
11 * Francois Chouinard - Updated as per TMF Event Model 1.0
12 * Alexandre Montplaisir - Removed Cloneable, made immutable
13 * Patrick Tasse - Remove getSubField
14 *******************************************************************************/
15
16 package org.eclipse.tracecompass.tmf.core.event;
17
18 import static org.eclipse.tracecompass.common.core.NonNullUtils.checkNotNull;
19
20 import java.util.Collection;
21 import java.util.Map;
22
23 import org.eclipse.jdt.annotation.NonNull;
24 import org.eclipse.jdt.annotation.Nullable;
25
26 import com.google.common.base.Joiner;
27 import com.google.common.collect.ImmutableMap;
28
29 /**
30 * A basic implementation of ITmfEventField.
31 * <p>
32 * Non-value fields are structural (i.e. used to represent the event structure
33 * including optional fields) while the valued fields are actual event fields.
34 *
35 * @version 1.0
36 * @author Francois Chouinard
37 *
38 * @see ITmfEvent
39 * @see ITmfEventType
40 */
41 public class TmfEventField implements ITmfEventField {
42
43 // ------------------------------------------------------------------------
44 // Attributes
45 // ------------------------------------------------------------------------
46
47 private final @NonNull String fName;
48 private final @Nullable Object fValue;
49 private final @NonNull Map<String, ITmfEventField> fFields;
50
51 // ------------------------------------------------------------------------
52 // Constructors
53 // ------------------------------------------------------------------------
54
55 /**
56 * Full constructor
57 *
58 * @param name
59 * the event field id
60 * @param value
61 * the event field value
62 * @param fields
63 * the list of subfields
64 * @throws IllegalArgumentException
65 * If 'name' is null, or if 'fields' has duplicate field names.
66 */
67 public TmfEventField(String name, @Nullable Object value, @Nullable ITmfEventField[] fields) {
68 if (name == null) {
69 throw new IllegalArgumentException();
70 }
71 fName = name;
72 fValue = value;
73
74 if (fields == null) {
75 fFields = checkNotNull(ImmutableMap.<String, ITmfEventField> of());
76 } else {
77 /* Java 8 streams will make this even more simple! */
78 ImmutableMap.Builder<String, ITmfEventField> mapBuilder = new ImmutableMap.Builder<>();
79 for (ITmfEventField field : fields) {
80 final String curName = field.getName();
81 mapBuilder.put(curName, field);
82 }
83 fFields = checkNotNull(mapBuilder.build());
84 }
85 }
86
87 /**
88 * Copy constructor
89 *
90 * @param field the other event field
91 */
92 public TmfEventField(final TmfEventField field) {
93 if (field == null) {
94 throw new IllegalArgumentException();
95 }
96 fName = field.fName;
97 fValue = field.fValue;
98 fFields = field.fFields;
99 }
100
101 // ------------------------------------------------------------------------
102 // ITmfEventField
103 // ------------------------------------------------------------------------
104
105 @Override
106 public String getName() {
107 return fName;
108 }
109
110 @Override
111 public Object getValue() {
112 return fValue;
113 }
114
115 @Override
116 public Collection<String> getFieldNames() {
117 return fFields.keySet();
118 }
119
120 @Override
121 public Collection<ITmfEventField> getFields() {
122 return fFields.values();
123 }
124
125 @Override
126 public ITmfEventField getField(final String... path) {
127 if (path.length == 1) {
128 return fFields.get(path[0]);
129 }
130 ITmfEventField field = this;
131 for (String name : path) {
132 field = field.getField(name);
133 if (field == null) {
134 return null;
135 }
136 }
137 return field;
138 }
139
140 // ------------------------------------------------------------------------
141 // Operations
142 // ------------------------------------------------------------------------
143
144 /**
145 * Create a root field from a list of labels.
146 *
147 * @param labels the list of labels
148 * @return the (flat) root list
149 */
150 public static final ITmfEventField makeRoot(final String[] labels) {
151 final ITmfEventField[] fields = new ITmfEventField[labels.length];
152 for (int i = 0; i < labels.length; i++) {
153 fields[i] = new TmfEventField(labels[i], null, null);
154 }
155 // Return a new root field;
156 return new TmfEventField(ITmfEventField.ROOT_FIELD_ID, null, fields);
157 }
158
159 // ------------------------------------------------------------------------
160 // Object
161 // ------------------------------------------------------------------------
162
163 @Override
164 public int hashCode() {
165 Object value = fValue;
166 final int prime = 31;
167 int result = 1;
168 result = prime * result + fName.hashCode();
169 result = prime * result + ((value == null) ? 0 : value.hashCode());
170 result = prime * result + fFields.hashCode();
171 return result;
172 }
173
174 @Override
175 public boolean equals(final Object obj) {
176 if (this == obj) {
177 return true;
178 }
179 if (obj == null) {
180 return false;
181 }
182 if (!(obj instanceof TmfEventField)) {
183 return false;
184 }
185
186 final TmfEventField other = (TmfEventField) obj;
187
188 /* Check that 'fName' is the same */
189 if (!fName.equals(other.fName)) {
190 return false;
191 }
192
193 /* Check that 'fValue' is the same */
194 Object value = this.fValue;
195 if (value == null) {
196 if (other.fValue != null) {
197 return false;
198 }
199 } else if (!value.equals(other.fValue)) {
200 return false;
201 }
202
203 /* Check that 'fFields' are the same */
204 if (!fFields.equals(other.fFields)) {
205 return false;
206 }
207
208 return true;
209 }
210
211 @Override
212 public String toString() {
213 StringBuilder ret = new StringBuilder();
214 if (fName.equals(ITmfEventField.ROOT_FIELD_ID)) {
215 /*
216 * If this field is a top-level "field container", we will print its
217 * sub-fields directly.
218 */
219 appendSubFields(ret);
220
221 } else {
222 /* The field has its own values */
223 ret.append(fName);
224 ret.append('=');
225 ret.append(fValue);
226
227 if (!fFields.isEmpty()) {
228 /*
229 * In addition to its own name/value, this field also has
230 * sub-fields.
231 */
232 ret.append(" ["); //$NON-NLS-1$
233 appendSubFields(ret);
234 ret.append(']');
235 }
236 }
237 return ret.toString();
238 }
239
240 private void appendSubFields(StringBuilder sb) {
241 Joiner joiner = Joiner.on(", ").skipNulls(); //$NON-NLS-1$
242 sb.append(joiner.join(getFields()));
243 }
244
245 @Override
246 public String getFormattedValue() {
247 return getValue().toString();
248 }
249
250 }
This page took 0.036748 seconds and 6 git commands to generate.