fec8dc4c1fe416b17a329c31cf927f25b13c6b0a
[deliverable/tracecompass.git] / org.eclipse.linuxtools.tmf.core / src / org / eclipse / linuxtools / internal / tmf / core / statesystem / Attribute.java
1 /*******************************************************************************
2 * Copyright (c) 2012 Ericsson
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 *******************************************************************************/
12
13 package org.eclipse.linuxtools.internal.tmf.core.statesystem;
14
15 import java.io.PrintWriter;
16 import java.util.ArrayList;
17 import java.util.Collections;
18 import java.util.HashMap;
19 import java.util.LinkedList;
20 import java.util.List;
21 import java.util.Map;
22
23 /**
24 * An Attribute is a "node" in the Attribute Tree. It represents a smallest
25 * unit of the model which can be in a particular state at a given time.
26 *
27 * It is abstract, as different implementations can provide different ways to
28 * access sub-attributes
29 *
30 * @author alexmont
31 *
32 */
33 abstract class Attribute {
34
35 private final Attribute parent;
36 private final String name;
37 private final int quark;
38 protected final List<Attribute> subAttributes;
39
40 /**
41 * Constructor
42 */
43 Attribute(Attribute parent, String name, int quark) {
44 this.parent = parent;
45 this.quark = quark;
46 this.name = name;
47 this.subAttributes = new ArrayList<>();
48 }
49
50 /**
51 * @name Accessors
52 */
53
54 int getQuark() {
55 return quark;
56 }
57
58 Attribute getParent() {
59 return parent;
60 }
61
62 List<Attribute> getSubAttributes() {
63 return Collections.unmodifiableList(subAttributes);
64 }
65
66 String getName() {
67 return name;
68 }
69
70 /**
71 * Get the matching quark for a given path-of-strings
72 *
73 * @param path
74 * The path we are looking for, *relative to this node*.
75 * @return The matching quark, or -1 if that attribute does not exist.
76 */
77 int getSubAttributeQuark(String... path) {
78 return this.getSubAttributeQuark(path, 0);
79 }
80
81 /**
82 * Other method to search through the attribute tree, but instead of
83 * returning the matching quark we return the AttributeTreeNode object
84 * itself. It can then be used as new "root node" for faster queries on the
85 * tree.
86 *
87 * @param path
88 * The target path, *relative to this node*
89 * @return The Node object matching the last element in the path, or "null"
90 * if that attribute does not exist.
91 */
92 Attribute getSubAttributeNode(String... path) {
93 return this.getSubAttributeNode(path, 0);
94 }
95
96 /**
97 * "Inner" part of the previous public method, which is used recursively. To
98 * avoid having to copy sub-arrays to pass down, we just track where we are
99 * at with the index parameter. It uses getSubAttributeNode(), whose
100 * implementation is left to the derived classes.
101 */
102 private int getSubAttributeQuark(String[] path, int index) {
103 Attribute targetNode = this.getSubAttributeNode(path, index);
104 if (targetNode == null) {
105 return -1;
106 }
107 return targetNode.getQuark();
108 }
109
110 /* The methods how to access children are left to derived classes */
111 abstract void addSubAttribute(Attribute newSubAttribute);
112 abstract Attribute getSubAttributeNode(String[] path, int index);
113
114 /**
115 * Return a String array composed of the full (absolute) path representing
116 * this attribute
117 *
118 * @return
119 */
120 String[] getFullAttribute() {
121 LinkedList<String> list = new LinkedList<>();
122 Attribute curNode = this;
123
124 /* Add recursive parents to the list, but stop at the root node */
125 while (curNode.getParent() != null) {
126 list.addFirst(curNode.getName());
127 curNode = curNode.getParent();
128 }
129
130 return list.toArray(new String[0]);
131 }
132
133 /**
134 * Return the absolute path of this attribute, as a single slash-separated
135 * String.
136 *
137 * @return
138 */
139 String getFullAttributeName() {
140 String[] array = this.getFullAttribute();
141 StringBuffer buf = new StringBuffer();
142
143 for (int i = 0; i < array.length - 1; i++) {
144 buf.append(array[i]);
145 buf.append('/');
146 }
147 buf.append(array[array.length - 1]);
148 return buf.toString();
149 }
150
151 @Override
152 public String toString() {
153 return getFullAttributeName() + " (" + quark + ')'; //$NON-NLS-1$
154 }
155
156 private int curDepth;
157
158 private void attributeNodeToString(PrintWriter writer, Attribute currentNode) {
159 int j;
160
161 writer.println(currentNode.getName() + " (" + currentNode.quark + ')'); //$NON-NLS-1$
162 curDepth++;
163
164 for (Attribute nextNode : currentNode.getSubAttributes()) {
165 /* Skip printing 'null' entries */
166 if (nextNode == null) {
167 continue;
168 }
169 for (j = 0; j < curDepth - 1; j++) {
170 writer.print(" "); //$NON-NLS-1$
171 }
172 writer.print(" "); //$NON-NLS-1$
173 attributeNodeToString(writer, nextNode);
174 }
175 curDepth--;
176 return;
177 }
178
179 void debugPrint(PrintWriter writer) {
180 /* Only used for debugging, shouldn't be externalized */
181 writer.println("------------------------------"); //$NON-NLS-1$
182 writer.println("Attribute tree: (quark)\n"); //$NON-NLS-1$
183 curDepth = 0;
184 attributeNodeToString(writer, this);
185 writer.print('\n');
186 }
187 }
188
189 /**
190 * This is the basic implementation, where sub-attributes names can be composed
191 * of any alphanumeric characters, and are stored as Strings. A HashMap is used
192 * to access them.
193 *
194 * @author alexmont
195 *
196 */
197 final class AlphaNumAttribute extends Attribute {
198
199 private Map<String, Integer> subAttributesMap;
200
201 AlphaNumAttribute(Attribute parent, String name, int quark) {
202 super(parent, name, quark);
203 this.subAttributesMap = new HashMap<>();
204 }
205
206 @Override
207 synchronized void addSubAttribute(Attribute newSubAttribute) {
208 assert (newSubAttribute != null);
209 assert (newSubAttribute.getName() != null);
210 /* This should catch buggy state changing statements */
211 assert (!newSubAttribute.getName().equals(this.getName()));
212
213 subAttributesMap.put(newSubAttribute.getName(), subAttributes.size());
214 subAttributes.add(newSubAttribute);
215 }
216
217 @Override
218 protected synchronized Attribute getSubAttributeNode(String[] path,
219 int index) {
220 Integer indexOfNextNode = subAttributesMap.get(path[index]);
221 Attribute nextNode;
222
223 if (indexOfNextNode == null) {
224 /* We don't have the expected child => the attribute does not exist */
225 return null;
226 }
227 if (index == path.length - 1) {
228 /* It's our job to process this request */
229 return subAttributes.get(indexOfNextNode);
230 }
231
232 nextNode = subAttributes.get(indexOfNextNode);
233 return nextNode.getSubAttributeNode(path, index + 1);
234 }
235 }
This page took 0.036197 seconds and 4 git commands to generate.