Commit | Line | Data |
---|---|---|
63c43609 MR |
1 | /******************************************************************************* |
2 | * Copyright (c) 2014 École Polytechnique de Montréal | |
3 | * | |
4 | * All rights reserved. This program and the accompanying materials are | |
5 | * made 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 | * Mathieu Rail - Initial API and implementation | |
11 | * Guilliano Molaire - Initial API and implementation | |
12 | *******************************************************************************/ | |
13 | ||
2bdf0193 | 14 | package org.eclipse.tracecompass.tmf.core.analysis; |
63c43609 | 15 | |
26683871 | 16 | import java.util.HashMap; |
63c43609 MR |
17 | import java.util.HashSet; |
18 | import java.util.Map; | |
26683871 | 19 | import java.util.Map.Entry; |
63c43609 MR |
20 | import java.util.Set; |
21 | ||
26683871 | 22 | import org.eclipse.jdt.annotation.NonNull; |
2bdf0193 AM |
23 | import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace; |
24 | import org.eclipse.tracecompass.tmf.core.trace.ITmfTraceWithPreDefinedEvents; | |
25 | import org.eclipse.tracecompass.tmf.core.trace.TmfEventTypeCollectionHelper; | |
26683871 | 26 | |
63c43609 MR |
27 | /** |
28 | * Class that contains all the values associated with a type needed by an | |
29 | * analysis in order to execute. Each value is peered with a level that | |
30 | * determines the importance of that specific value for the requirement. | |
31 | * | |
32 | * The type gives an indication about the kind of value the requirement | |
33 | * contains. The value should depend on the type. For instance, a requirement | |
34 | * type could be "event" and all the values that would be added in the | |
35 | * requirement object could indicate the possible events handled by the | |
36 | * analysis. | |
37 | * | |
38 | * For these values, a level will be assigned indicating how important the value | |
39 | * is based on two possibilities: Mandatory or optional. | |
40 | * | |
41 | * Moreover, useful information that can not be leveled with a priority but are | |
42 | * important for the proper execution of an analysis can be added. | |
43 | * | |
44 | * @author Guilliano Molaire | |
45 | * @author Mathieu Rail | |
63c43609 MR |
46 | */ |
47 | public class TmfAnalysisRequirement { | |
48 | ||
26683871 GB |
49 | /** |
50 | * String for requirement type 'event', that can be used by analysis | |
51 | */ | |
52 | public static final String TYPE_EVENT = "event"; //$NON-NLS-1$ | |
53 | ||
63c43609 MR |
54 | private final String fType; |
55 | private final Map<String, ValuePriorityLevel> fValues = new HashMap<>(); | |
56 | private final Set<String> fInformation = new HashSet<>(); | |
57 | ||
58 | /** | |
59 | * The possible level for each value. They must be listed in ascending order | |
60 | * of priority. | |
61 | */ | |
62 | public enum ValuePriorityLevel { | |
63 | /** The value could be absent and the analysis would still work */ | |
64 | OPTIONAL, | |
65 | /** The value must be present at runtime (for the analysis) */ | |
66 | MANDATORY | |
67 | } | |
68 | ||
69 | /** | |
70 | * Constructor | |
71 | * | |
72 | * @param type | |
73 | * The type of the requirement | |
74 | */ | |
75 | public TmfAnalysisRequirement(String type) { | |
76 | fType = type; | |
77 | } | |
78 | ||
79 | /** | |
80 | * Constructor. Instantiate a requirement object with a list of values of | |
81 | * the same level | |
82 | * | |
83 | * @param type | |
84 | * The type of the requirement | |
85 | * @param values | |
86 | * All the values associated with that type | |
87 | * @param level | |
88 | * A level associated with all the values | |
89 | */ | |
90 | public TmfAnalysisRequirement(String type, Iterable<String> values, ValuePriorityLevel level) { | |
91 | fType = type; | |
92 | addValues(values, level); | |
93 | } | |
94 | ||
95 | /** | |
96 | * Merges the values of the specified requirement with those of this | |
97 | * requirement. All new values will retain their priority value level. If a | |
98 | * value was already inside the current requirement, the current priority | |
99 | * level will be overridden if the new priority level is higher. | |
100 | * | |
101 | * @param subRequirement | |
102 | * The requirement to be merged into the current one | |
103 | * @param maxSubRequirementValueLevel | |
104 | * The level associated with all the new values or currently | |
105 | * lower priority ones | |
106 | * @return True if the merge was successful | |
107 | */ | |
108 | public Boolean merge(TmfAnalysisRequirement subRequirement, ValuePriorityLevel maxSubRequirementValueLevel) { | |
109 | /* Two requirements can't be merged if their types are different */ | |
110 | if (!isSameType(subRequirement)) { | |
111 | return false; | |
112 | } | |
113 | ||
114 | Set<String> values = subRequirement.getValues(); | |
115 | for (String value : values) { | |
116 | /* | |
117 | * Sub-requirement value levels are limited to | |
118 | * maxSubRequirementValueLevel, so the level associated with the | |
119 | * values in the merge is the minimum value between | |
120 | * maxSubRequirementValueLevel and its true level. | |
121 | */ | |
122 | int minLevel = Math.min(subRequirement.getValueLevel(value).ordinal(), maxSubRequirementValueLevel.ordinal()); | |
123 | ValuePriorityLevel subRequirementValueLevel = ValuePriorityLevel.values()[minLevel]; | |
124 | ||
125 | if (fValues.containsKey(value)) { | |
126 | /* | |
127 | * If a value is already in a requirement, we update the level | |
128 | * by the highest value between the current level in the | |
129 | * requirement and the level of the value in the | |
130 | * sub-requirement. | |
131 | */ | |
132 | ValuePriorityLevel requirementValueLevel = getValueLevel(value); | |
133 | ||
134 | int newValueLevel = Math.max(requirementValueLevel.ordinal(), subRequirementValueLevel.ordinal()); | |
135 | ValuePriorityLevel highestLevel = ValuePriorityLevel.values()[newValueLevel]; | |
136 | addValue(value, highestLevel); | |
137 | } | |
138 | else { | |
139 | addValue(value, subRequirementValueLevel); | |
140 | } | |
141 | } | |
142 | ||
143 | /* Merge the information */ | |
144 | fInformation.addAll(subRequirement.getInformation()); | |
145 | ||
146 | return true; | |
147 | } | |
148 | ||
149 | /** | |
150 | * Adds a list of value inside the requirement with the same level. | |
151 | * | |
152 | * @param values | |
153 | * A list of value | |
154 | * @param level | |
155 | * The level associated with all the values | |
156 | */ | |
157 | public void addValues(Iterable<String> values, ValuePriorityLevel level) { | |
158 | for (String value : values) { | |
159 | addValue(value, level); | |
160 | } | |
161 | } | |
162 | ||
163 | /** | |
164 | * Adds a value with his associated level into the requirement. If the value | |
165 | * is already contained in the requirement the method modifies its existing | |
166 | * value level. | |
167 | * | |
168 | * @param value | |
169 | * The value | |
170 | * @param level | |
171 | * The level | |
172 | */ | |
173 | public void addValue(String value, ValuePriorityLevel level) { | |
174 | synchronized (fValues) { | |
175 | fValues.put(value, level); | |
176 | } | |
177 | } | |
178 | ||
179 | /** | |
180 | * Adds an information about the requirement. | |
181 | * | |
182 | * @param information | |
183 | * The information to be added | |
184 | */ | |
185 | public void addInformation(String information) { | |
186 | fInformation.add(information); | |
187 | } | |
188 | ||
189 | /** | |
190 | * Determines if the analysis requirement has the same type of another | |
191 | * requirement. | |
192 | * | |
193 | * @param requirement | |
194 | * Requirement whose type is to be compared to this requirement's | |
195 | * type. | |
196 | * @return True if the two requirements have the same type; otherwise false | |
197 | */ | |
198 | public Boolean isSameType(TmfAnalysisRequirement requirement) { | |
199 | return fType.equals(requirement.getType()); | |
200 | } | |
201 | ||
202 | /** | |
203 | * Gets the requirement type. The type is read only. | |
204 | * | |
205 | * @return The type of this requirement | |
206 | */ | |
207 | public String getType() { | |
208 | return fType; | |
209 | } | |
210 | ||
211 | /** | |
212 | * Gets all the values associated with the requirement. | |
213 | * | |
214 | * @return Set containing the values | |
215 | */ | |
216 | public Set<String> getValues() { | |
217 | synchronized (fValues) { | |
218 | return fValues.keySet(); | |
219 | } | |
220 | } | |
221 | ||
26683871 GB |
222 | /** |
223 | * Gets all the values associated with the requirement with a given priority | |
224 | * level. | |
225 | * | |
226 | * @param level | |
227 | * The desired level | |
228 | * @return Set containing the values with the given priority level | |
229 | */ | |
230 | public Set<String> getValues(ValuePriorityLevel level) { | |
231 | synchronized (fValues) { | |
232 | Set<String> values = new HashSet<>(); | |
233 | for (Entry<String, ValuePriorityLevel> entry : fValues.entrySet()) { | |
234 | if (entry.getValue() == level) { | |
235 | values.add(entry.getKey()); | |
236 | } | |
237 | } | |
238 | return values; | |
239 | } | |
240 | } | |
241 | ||
63c43609 MR |
242 | /** |
243 | * Gets information about the requirement. | |
244 | * | |
245 | * @return The set of all the information | |
246 | */ | |
247 | public Set<String> getInformation() { | |
248 | return fInformation; | |
249 | } | |
250 | ||
251 | /** | |
252 | * Gets the level associated with a particular type | |
253 | * | |
254 | * @param value | |
255 | * The value | |
256 | * @return The level or null if the value does not exist | |
257 | */ | |
258 | public ValuePriorityLevel getValueLevel(String value) { | |
259 | synchronized (fValues) { | |
260 | return fValues.get(value); | |
261 | } | |
262 | } | |
26683871 GB |
263 | |
264 | /** | |
265 | * Verifies whether a trace fulfills this requirement | |
266 | * | |
267 | * @param trace | |
268 | * The trace on which to check for this requirement | |
269 | * @return True if the trace has all mandatory values of this requirement | |
270 | */ | |
271 | public boolean isFulfilled(@NonNull ITmfTrace trace) { | |
272 | switch (fType) { | |
273 | case TYPE_EVENT: | |
274 | if (trace instanceof ITmfTraceWithPreDefinedEvents) { | |
275 | Set<String> traceEvents = TmfEventTypeCollectionHelper.getEventNames(((ITmfTraceWithPreDefinedEvents) trace).getContainedEventTypes()); | |
276 | Set<String> mandatoryValues = getValues(ValuePriorityLevel.MANDATORY); | |
277 | return traceEvents.containsAll(mandatoryValues); | |
278 | } | |
279 | break; | |
280 | default: | |
281 | return true; | |
282 | } | |
283 | return true; | |
284 | } | |
285 | ||
286 | @Override | |
287 | public String toString() { | |
288 | return fType + ": " + fValues; //$NON-NLS-1$ | |
289 | } | |
63c43609 | 290 | } |