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