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