tmf: Add generics to ITmfEventAspect
[deliverable/tracecompass.git] / tmf / org.eclipse.tracecompass.tmf.core / src / org / eclipse / tracecompass / tmf / core / event / aspect / TmfEventFieldAspect.java
1 /*******************************************************************************
2 * Copyright (c) 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 * Patrick Tasse - Initial API and implementation
11 *******************************************************************************/
12
13 package org.eclipse.tracecompass.tmf.core.event.aspect;
14
15 import java.util.ArrayList;
16 import java.util.List;
17
18 import org.eclipse.jdt.annotation.Nullable;
19 import org.eclipse.tracecompass.tmf.core.event.ITmfEvent;
20 import org.eclipse.tracecompass.tmf.core.event.ITmfEventField;
21
22 /**
23 * Event aspect that resolves to a root event field, or one of its subfields.
24 *
25 * When used, the subfield pattern is slash-prefixed and slash-separated, and
26 * the backslash character is used to escape an uninterpreted slash.
27 *
28 * @author Patrick Tasse
29 */
30 public class TmfEventFieldAspect implements ITmfEventAspect<Object> {
31
32 private static final char SLASH = '/';
33 private static final char BACKSLASH = '\\';
34
35 private final String fAspectName;
36 private final IRootField fRootField;
37 private final @Nullable String fFieldPath;
38 private final String[] fFieldArray;
39
40 /**
41 * Interface for the root field resolver
42 */
43 public interface IRootField {
44 /**
45 * Returns the root event field for this aspect. Implementations must
46 * override to provide a specific event member but should not assume the
47 * event is of any specific type.
48 *
49 * @param event
50 * The event to process
51 * @return the root event field
52 */
53 public @Nullable ITmfEventField getRootField(ITmfEvent event);
54 }
55
56 /**
57 * Constructor
58 *
59 * @param aspectName
60 * The name of the aspect. Should be localized.
61 * @param fieldPath
62 * The field name or subfield pattern to resolve the event, or
63 * null to use the root field. Should *not* be localized!
64 * @param rootField
65 * The root field resolver object
66 */
67 public TmfEventFieldAspect(String aspectName, @Nullable String fieldPath, IRootField rootField) {
68 fAspectName = aspectName;
69 fFieldPath = fieldPath;
70 fFieldArray = getFieldArray(fieldPath);
71 fRootField = rootField;
72 }
73
74 /**
75 * Get the field name or subfield pattern to resolve the event, or null if
76 * the root field is used.
77 *
78 * @return the field name, subfield pattern, or null
79 */
80 public @Nullable String getFieldPath() {
81 return fFieldPath;
82 }
83
84 /**
85 * Create a new instance of the aspect for the specified field name or
86 * subfield pattern, relative to the root field, or null for the root
87 * field.
88 *
89 * @param fieldPath
90 * The field name or subfield pattern to resolve the event, or
91 * null.
92 * @return a new aspect instance
93 */
94 public TmfEventFieldAspect forField(@Nullable String fieldPath) {
95 return new TmfEventFieldAspect(fAspectName, fieldPath, fRootField);
96 }
97
98 @Override
99 public String getName() {
100 return fAspectName;
101 }
102
103 @Override
104 public String getHelpText() {
105 return EMPTY_STRING;
106 }
107
108 @Override
109 public @Nullable Object resolve(ITmfEvent event) {
110 ITmfEventField root = fRootField.getRootField(event);
111 if (root == null) {
112 return null;
113 }
114 if (fFieldArray.length == 0) {
115 return root;
116 }
117 ITmfEventField field = root.getField(fFieldArray);
118 if (field == null) {
119 return null;
120 }
121 return field.getValue();
122 }
123
124 // ------------------------------------------------------------------------
125 // hashCode/equals
126 // Typically we want identical field aspects to be merged together.
127 // ------------------------------------------------------------------------
128
129 @Override
130 public int hashCode() {
131 final int prime = 31;
132 int result = 1;
133 result = prime * result + fAspectName.hashCode();
134 String fieldPath = fFieldPath;
135 result = prime * result + (fieldPath == null ? 0 : fieldPath.hashCode());
136 return result;
137 }
138
139 @Override
140 public boolean equals(@Nullable Object obj) {
141 if (this == obj) {
142 return true;
143 }
144 if (obj == null) {
145 return false;
146 }
147 if (!this.getClass().equals(obj.getClass())) {
148 return false;
149 }
150 TmfEventFieldAspect other = (TmfEventFieldAspect) obj;
151 if (!fAspectName.equals(other.fAspectName)) {
152 return false;
153 }
154 String fieldPath = fFieldPath;
155 if (fieldPath == null) {
156 if (other.fFieldPath != null) {
157 return false;
158 }
159 } else if (!fieldPath.equals(other.fFieldPath)) {
160 return false;
161 }
162 return true;
163 }
164
165 private static String[] getFieldArray(@Nullable String field) {
166
167 if (field == null) {
168 return new String[0];
169 }
170
171 if (field.charAt(0) != SLASH) {
172 return new String[] { field };
173 }
174
175 StringBuilder sb = new StringBuilder();
176 List<String> list = new ArrayList<>();
177
178 // We start at 1 since the first character is a slash that we want to
179 // ignore.
180 for (int i = 1; i < field.length(); i++) {
181 char charAt = field.charAt(i);
182 if (charAt == SLASH) {
183 // char is slash. Cut here.
184 list.add(sb.toString());
185 sb = new StringBuilder();
186 } else if ((charAt == BACKSLASH) && (i < field.length() - 1) && (field.charAt(i + 1) == SLASH)) {
187 // Uninterpreted slash. Add it.
188 sb.append(SLASH);
189 i++;
190 } else {
191 // Any other character. Add.
192 sb.append(charAt);
193 }
194 }
195
196 // Last block. Add it to list.
197 list.add(sb.toString());
198
199 // Transform to array
200 String[] array = new String[list.size()];
201 list.toArray(array);
202
203 return array;
204 }
205 }
This page took 0.058358 seconds and 5 git commands to generate.