analysis: Move plugins to their own sub-directory
[deliverable/tracecompass.git] / org.eclipse.tracecompass.tmf.core / src / org / eclipse / tracecompass / tmf / core / analysis / TmfAnalysisRequirement.java
CommitLineData
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 14package org.eclipse.tracecompass.tmf.core.analysis;
63c43609 15
26683871 16import java.util.HashMap;
63c43609
MR
17import java.util.HashSet;
18import java.util.Map;
26683871 19import java.util.Map.Entry;
63c43609
MR
20import java.util.Set;
21
26683871 22import org.eclipse.jdt.annotation.NonNull;
2bdf0193
AM
23import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace;
24import org.eclipse.tracecompass.tmf.core.trace.ITmfTraceWithPreDefinedEvents;
25import 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 */
47public 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}
This page took 0.065144 seconds and 5 git commands to generate.