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>
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
11 *******************************************************************************/
13 package org
.eclipse
.linuxtools
.tmf
.core
.statesystem
;
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
;
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.
26 * It is abstract, as different implementations can provide different ways to
27 * access sub-attributes
32 abstract class Attribute
{
34 private final Attribute parent
;
35 private final String name
;
36 private final int quark
;
37 protected final Vector
<Attribute
> subAttributes
;
42 Attribute(Attribute parent
, String name
, int quark
) {
46 this.subAttributes
= new Vector
<Attribute
>();
57 Attribute
getParent() {
61 List
<Attribute
> getSubAttributesList() {
70 * Get the matching quark for a given path-of-strings
73 * The path we are looking for, *relative to this node*.
74 * @return The matching quark, or -1 if that attribute does not exist.
76 int getSubAttributeQuark(String
... path
) {
77 return this.getSubAttributeQuark(path
, 0);
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
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.
91 Attribute
getSubAttributeNode(String
... path
) {
92 return this.getSubAttributeNode(path
, 0);
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.
101 private int getSubAttributeQuark(String
[] path
, int index
) {
102 Attribute targetNode
= this.getSubAttributeNode(path
, index
);
103 if (targetNode
== null) {
106 return targetNode
.getQuark();
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
);
114 * Return a String array composed of the full (absolute) path representing
119 String
[] getFullAttribute() {
120 LinkedList
<String
> list
= new LinkedList
<String
>();
121 Attribute curNode
= this;
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();
129 Collections
.reverse(list
);
131 return list
.toArray(new String
[0]);
135 * Return the absolute path of this attribute, as a single slash-separated
140 String
getFullAttributeName() {
142 String ret
= ""; //$NON-NLS-1$
144 array
= this.getFullAttribute();
145 for (int i
= 0; i
< array
.length
- 1; i
++) {
146 ret
+= array
[i
] + '/';
148 ret
+= array
[array
.length
- 1];
153 public String
toString() {
154 return getFullAttributeName() + " (" + quark
+ ')'; //$NON-NLS-1$
157 private int curDepth
;
159 private void attributeNodeToString(PrintWriter writer
, Attribute currentNode
) {
162 writer
.println(currentNode
.getName() + " (" + currentNode
.quark
+ ')'); //$NON-NLS-1$
165 for (Attribute nextNode
: currentNode
.getSubAttributesList()) {
166 /* Skip printing 'null' entries */
167 if (nextNode
== null) {
170 for (j
= 0; j
< curDepth
- 1; j
++) {
171 writer
.print(" "); //$NON-NLS-1$
173 writer
.print(" "); //$NON-NLS-1$
174 attributeNodeToString(writer
, nextNode
);
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$
185 attributeNodeToString(writer
, this);
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
198 final class AlphaNumAttribute
extends Attribute
{
200 private HashMap
<String
, Integer
> subAttributesMap
;
202 AlphaNumAttribute(Attribute parent
, String name
, int quark
) {
203 super(parent
, name
, quark
);
204 this.subAttributesMap
= new HashMap
<String
, Integer
>();
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()));
214 subAttributesMap
.put(newSubAttribute
.getName(), subAttributes
.size());
215 subAttributes
.add(newSubAttribute
);
219 protected synchronized Attribute
getSubAttributeNode(String
[] path
,
221 Integer indexOfNextNode
= subAttributesMap
.get(path
[index
]);
224 if (indexOfNextNode
== null) {
225 /* We don't have the expected child => the attribute does not exist */
228 if (index
== path
.length
- 1) {
229 /* It's our job to process this request */
230 return subAttributes
.get(indexOfNextNode
);
233 nextNode
= subAttributes
.get(indexOfNextNode
);
234 return nextNode
.getSubAttributeNode(path
, index
+ 1);