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