1 /*******************************************************************************
2 * Copyright (c) 2014 École Polytechnique de Montréal
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
10 * Mathieu Rail - Initial API and implementation
11 * Guilliano Molaire - Initial API and implementation
12 *******************************************************************************/
14 package org
.eclipse
.linuxtools
.tmf
.core
.analysis
;
16 import java
.util
.HashMap
;
17 import java
.util
.HashSet
;
19 import java
.util
.Map
.Entry
;
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
;
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.
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
38 * For these values, a level will be assigned indicating how important the value
39 * is based on two possibilities: Mandatory or optional.
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.
44 * @author Guilliano Molaire
45 * @author Mathieu Rail
48 public class TmfAnalysisRequirement
{
51 * String for requirement type 'event', that can be used by analysis
53 public static final String TYPE_EVENT
= "event"; //$NON-NLS-1$
55 private final String fType
;
56 private final Map
<String
, ValuePriorityLevel
> fValues
= new HashMap
<>();
57 private final Set
<String
> fInformation
= new HashSet
<>();
60 * The possible level for each value. They must be listed in ascending order
63 public enum ValuePriorityLevel
{
64 /** The value could be absent and the analysis would still work */
66 /** The value must be present at runtime (for the analysis) */
74 * The type of the requirement
76 public TmfAnalysisRequirement(String type
) {
81 * Constructor. Instantiate a requirement object with a list of values of
85 * The type of the requirement
87 * All the values associated with that type
89 * A level associated with all the values
91 public TmfAnalysisRequirement(String type
, Iterable
<String
> values
, ValuePriorityLevel level
) {
93 addValues(values
, level
);
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.
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
109 public Boolean
merge(TmfAnalysisRequirement subRequirement
, ValuePriorityLevel maxSubRequirementValueLevel
) {
110 /* Two requirements can't be merged if their types are different */
111 if (!isSameType(subRequirement
)) {
115 Set
<String
> values
= subRequirement
.getValues();
116 for (String value
: values
) {
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.
123 int minLevel
= Math
.min(subRequirement
.getValueLevel(value
).ordinal(), maxSubRequirementValueLevel
.ordinal());
124 ValuePriorityLevel subRequirementValueLevel
= ValuePriorityLevel
.values()[minLevel
];
126 if (fValues
.containsKey(value
)) {
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
133 ValuePriorityLevel requirementValueLevel
= getValueLevel(value
);
135 int newValueLevel
= Math
.max(requirementValueLevel
.ordinal(), subRequirementValueLevel
.ordinal());
136 ValuePriorityLevel highestLevel
= ValuePriorityLevel
.values()[newValueLevel
];
137 addValue(value
, highestLevel
);
140 addValue(value
, subRequirementValueLevel
);
144 /* Merge the information */
145 fInformation
.addAll(subRequirement
.getInformation());
151 * Adds a list of value inside the requirement with the same level.
156 * The level associated with all the values
158 public void addValues(Iterable
<String
> values
, ValuePriorityLevel level
) {
159 for (String value
: values
) {
160 addValue(value
, level
);
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
174 public void addValue(String value
, ValuePriorityLevel level
) {
175 synchronized (fValues
) {
176 fValues
.put(value
, level
);
181 * Adds an information about the requirement.
184 * The information to be added
186 public void addInformation(String information
) {
187 fInformation
.add(information
);
191 * Determines if the analysis requirement has the same type of another
195 * Requirement whose type is to be compared to this requirement's
197 * @return True if the two requirements have the same type; otherwise false
199 public Boolean
isSameType(TmfAnalysisRequirement requirement
) {
200 return fType
.equals(requirement
.getType());
204 * Gets the requirement type. The type is read only.
206 * @return The type of this requirement
208 public String
getType() {
213 * Gets all the values associated with the requirement.
215 * @return Set containing the values
217 public Set
<String
> getValues() {
218 synchronized (fValues
) {
219 return fValues
.keySet();
224 * Gets all the values associated with the requirement with a given priority
229 * @return Set containing the values with the given priority level
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());
244 * Gets information about the requirement.
246 * @return The set of all the information
248 public Set
<String
> getInformation() {
253 * Gets the level associated with a particular type
257 * @return The level or null if the value does not exist
259 public ValuePriorityLevel
getValueLevel(String value
) {
260 synchronized (fValues
) {
261 return fValues
.get(value
);
266 * Verifies whether a trace fulfills this requirement
269 * The trace on which to check for this requirement
270 * @return True if the trace has all mandatory values of this requirement
272 public boolean isFulfilled(@NonNull ITmfTrace trace
) {
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
);
288 public String
toString() {
289 return fType
+ ": " + fValues
; //$NON-NLS-1$