ff26cc0f375cbed93d08c15f9fffc5d2132715a5
[deliverable/tracecompass.git] / statesystem / org.eclipse.tracecompass.statesystem.core / src / org / eclipse / tracecompass / internal / statesystem / core / Attribute.java
1 /*******************************************************************************
2 * Copyright (c) 2012, 2015 Ericsson, EfficiOS Inc.
3 * Copyright (c) 2010, 2011 École Polytechnique de Montréal
4 * Copyright (c) 2010, 2011 Alexandre Montplaisir <alexandre.montplaisir@gmail.com>
5 *
6 * All rights reserved. This program and the accompanying materials are
7 * made available under the terms of the Eclipse Public License v1.0 which
8 * accompanies this distribution, and is available at
9 * http://www.eclipse.org/legal/epl-v10.html
10 *
11 * Contributors:
12 * Alexandre Montplaisir - Initial API and implementation
13 *******************************************************************************/
14
15 package org.eclipse.tracecompass.internal.statesystem.core;
16
17 import static org.eclipse.tracecompass.common.core.NonNullUtils.checkNotNull;
18 import static org.eclipse.tracecompass.statesystem.core.ITmfStateSystem.INVALID_ATTRIBUTE;
19
20 import java.io.PrintWriter;
21 import java.util.Collections;
22 import java.util.LinkedHashMap;
23 import java.util.LinkedList;
24 import java.util.Map;
25
26 import org.eclipse.jdt.annotation.NonNull;
27 import org.eclipse.tracecompass.statesystem.core.ITmfStateSystem;
28
29 import com.google.common.collect.ImmutableList;
30
31 /**
32 * An Attribute is a "node" in the Attribute Tree. It represents a smallest
33 * unit of the model which can be in a particular state at a given time.
34 *
35 * It is abstract, as different implementations can provide different ways to
36 * access sub-attributes
37 *
38 * @author Alexandre Montplaisir
39 *
40 */
41 public final class Attribute {
42
43 private final Attribute parent;
44 private final @NonNull String name;
45 private final int quark;
46
47 /** The sub-attributes (<basename, attribute>) of this attribute */
48 private final Map<String, Attribute> subAttributes;
49
50 /**
51 * Constructor
52 *
53 * @param parent
54 * The parent attribute of this one. Can be 'null' to represent
55 * this attribute is the root node of the tree.
56 * @param name
57 * Base name of this attribute
58 * @param quark
59 * The integer representation of this attribute
60 */
61 public Attribute(Attribute parent, @NonNull String name, int quark) {
62 this.parent = parent;
63 this.quark = quark;
64 this.name = name;
65 this.subAttributes = Collections.synchronizedMap(new LinkedHashMap<String, Attribute>());
66 }
67
68 // ------------------------------------------------------------------------
69 // Accessors
70 // ------------------------------------------------------------------------
71
72 /**
73 * Get the quark (integer representation) of this attribute.
74 *
75 * @return The quark of this attribute
76 */
77 public int getQuark() {
78 return quark;
79 }
80
81 /**
82 * Get the name of this attribute.
83 *
84 * @return The name of this attribute
85 */
86 public @NonNull String getName() {
87 return name;
88 }
89
90 /**
91 * Get the list of child attributes below this one.
92 *
93 * @return The child attributes.
94 */
95 public Iterable<Attribute> getSubAttributes() {
96 return ImmutableList.copyOf(subAttributes.values());
97 }
98
99 /**
100 * Get the matching quark for a given path-of-strings
101 *
102 * @param path
103 * The path we are looking for, *relative to this node*.
104 * @return The matching quark, or {@link ITmfStateSystem#INVALID_ATTRIBUTE}
105 * if that attribute does not exist.
106 */
107 public int getSubAttributeQuark(String... path) {
108 return this.getSubAttributeQuark(path, 0);
109 }
110
111 /**
112 * Other method to search through the attribute tree, but instead of
113 * returning the matching quark we return the AttributeTreeNode object
114 * itself. It can then be used as new "root node" for faster queries on the
115 * tree.
116 *
117 * @param path
118 * The target path, *relative to this node*
119 * @return The Node object matching the last element in the path, or "null"
120 * if that attribute does not exist.
121 */
122 public Attribute getSubAttributeNode(String... path) {
123 return this.getSubAttributeNode(path, 0);
124 }
125
126 /**
127 * "Inner" part of the previous public method, which is used recursively. To
128 * avoid having to copy sub-arrays to pass down, we just track where we are
129 * at with the index parameter. It uses getSubAttributeNode(), whose
130 * implementation is left to the derived classes.
131 */
132 private int getSubAttributeQuark(String[] path, int index) {
133 Attribute targetNode = this.getSubAttributeNode(path, index);
134 if (targetNode == null) {
135 return INVALID_ATTRIBUTE;
136 }
137 return targetNode.getQuark();
138 }
139
140 /**
141 * Get the parent attribute of this attribute
142 *
143 * @return The parent attribute
144 */
145 public Attribute getParentAttribute() {
146 return this.parent;
147 }
148
149 /**
150 * Get the parent quark of this attribute
151 *
152 * @return The quark of the parent attribute
153 */
154 public int getParentAttributeQuark() {
155 return this.parent.getQuark();
156 }
157
158 /* The methods how to access children are left to derived classes */
159
160 /**
161 * Add a sub-attribute to this attribute
162 *
163 * @param newSubAttribute The new attribute to add
164 */
165 public void addSubAttribute(Attribute newSubAttribute) {
166 if (newSubAttribute == null) {
167 throw new IllegalArgumentException();
168 }
169 subAttributes.put(newSubAttribute.getName(), newSubAttribute);
170 }
171
172 /**
173 * Get a sub-attribute from this node's sub-attributes
174 *
175 * @param path
176 * The *full* path to the attribute
177 * @param index
178 * The index in 'path' where this attribute is located
179 * (indicating where to start searching).
180 * @return The requested attribute
181 */
182 private Attribute getSubAttributeNode(String[] path, int index) {
183 final Attribute nextNode = subAttributes.get(path[index]);
184
185 if (nextNode == null) {
186 /* We don't have the expected child => the attribute does not exist */
187 return null;
188 }
189 if (index == path.length - 1) {
190 /* It's our job to process this request */
191 return nextNode;
192 }
193
194 /* Pass on the rest of the path to the relevant child */
195 return nextNode.getSubAttributeNode(path, index + 1);
196 }
197
198 /**
199 * Return a String array composed of the full (absolute) path representing
200 * this attribute
201 *
202 * @return The full attribute path elements
203 */
204 public String @NonNull [] getFullAttribute() {
205 LinkedList<String> list = new LinkedList<>();
206 Attribute curNode = this;
207
208 /* Add recursive parents to the list, but stop at the root node */
209 while (curNode.parent != null) {
210 list.addFirst(curNode.getName());
211 curNode = curNode.parent;
212 }
213
214 return list.toArray(new String[0]);
215 }
216
217 /**
218 * Return the absolute path of this attribute, as a single slash-separated
219 * String.
220 *
221 * @return The full name of this attribute
222 */
223 public @NonNull String getFullAttributeName() {
224 String[] array = this.getFullAttribute();
225 StringBuffer buf = new StringBuffer();
226
227 for (int i = 0; i < array.length - 1; i++) {
228 buf.append(array[i]);
229 buf.append('/');
230 }
231 buf.append(array[array.length - 1]);
232 return checkNotNull(buf.toString());
233 }
234
235 @Override
236 public String toString() {
237 return getFullAttributeName() + " (" + quark + ')'; //$NON-NLS-1$
238 }
239
240 private int curDepth;
241
242 private void attributeNodeToString(PrintWriter writer, Attribute currentNode) {
243 writer.println(currentNode.getName() + " (" + currentNode.quark + ')'); //$NON-NLS-1$
244 curDepth++;
245
246 for (Attribute nextNode : currentNode.getSubAttributes()) {
247 /* Skip printing 'null' entries */
248 if (nextNode == null) {
249 continue;
250 }
251 for (int j = 0; j < curDepth - 1; j++) {
252 writer.print(" "); //$NON-NLS-1$
253 }
254 writer.print(" "); //$NON-NLS-1$
255 attributeNodeToString(writer, nextNode);
256 }
257 curDepth--;
258 return;
259 }
260
261 /**
262 * Debugging method to print the contents of this attribute
263 *
264 * @param writer
265 * PrintWriter where to write the information
266 */
267 public void debugPrint(PrintWriter writer) {
268 /* Only used for debugging, shouldn't be externalized */
269 writer.println("------------------------------"); //$NON-NLS-1$
270 writer.println("Attribute tree: (quark)\n"); //$NON-NLS-1$
271 curDepth = 0;
272 attributeNodeToString(writer, this);
273 writer.print('\n');
274 }
275 }
This page took 0.066842 seconds and 4 git commands to generate.