Fix some null warnings
[deliverable/tracecompass.git] / statesystem / org.eclipse.tracecompass.statesystem.core / src / org / eclipse / tracecompass / internal / statesystem / core / AttributeTree.java
CommitLineData
a52fde77 1/*******************************************************************************
e13bd4cd 2 * Copyright (c) 2012, 2015 Ericsson
a52fde77
AM
3 * Copyright (c) 2010, 2011 École Polytechnique de Montréal
4 * Copyright (c) 2010, 2011 Alexandre Montplaisir <alexandre.montplaisir@gmail.com>
8d1346f0 5 *
a52fde77
AM
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
8d1346f0 10 *
e13bd4cd
PT
11 * Contributors:
12 * Alexandre Montplaisir - Initial API and implementation
13 * Patrick Tasse - Add message to exceptions
a52fde77
AM
14 *******************************************************************************/
15
e894a508 16package org.eclipse.tracecompass.internal.statesystem.core;
a52fde77 17
04927a83
AM
18import static org.eclipse.tracecompass.common.core.NonNullUtils.checkNotNull;
19
085a78a8 20import java.io.BufferedInputStream;
085a78a8
AM
21import java.io.File;
22import java.io.FileInputStream;
da66cc75 23import java.io.FileOutputStream;
085a78a8 24import java.io.IOException;
da66cc75
AM
25import java.io.ObjectInputStream;
26import java.io.ObjectOutputStream;
085a78a8 27import java.io.PrintWriter;
da66cc75 28import java.nio.channels.FileChannel;
a52fde77
AM
29import java.util.ArrayList;
30import java.util.Arrays;
a52fde77
AM
31import java.util.List;
32
50a47aa6 33import org.eclipse.jdt.annotation.NonNull;
e894a508 34import org.eclipse.tracecompass.statesystem.core.exceptions.AttributeNotFoundException;
6d08acca 35
a52fde77
AM
36/**
37 * The Attribute Tree is the /proc-like filesystem used to organize attributes.
38 * Each node of this tree is both like a file and a directory in the
39 * "file system".
8d1346f0 40 *
a52fde77 41 * @author alexmont
8d1346f0 42 *
a52fde77 43 */
cb42195c 44public final class AttributeTree {
a52fde77
AM
45
46 /* "Magic number" for attribute tree files or file sections */
cb42195c 47 private static final int ATTRIB_TREE_MAGIC_NUMBER = 0x06EC3671;
a52fde77
AM
48
49 private final StateSystem ss;
50 private final List<Attribute> attributeList;
51 private final Attribute attributeTreeRoot;
52
53 /**
54 * Standard constructor, create a new empty Attribute Tree
8d1346f0 55 *
a52fde77
AM
56 * @param ss
57 * The StateSystem to which this AT is attached
58 */
a6917276 59 public AttributeTree(StateSystem ss) {
a52fde77 60 this.ss = ss;
a69a9003 61 this.attributeList = new ArrayList<>();
c3f21a07 62 this.attributeTreeRoot = new Attribute(null, "root", -1); //$NON-NLS-1$
a52fde77
AM
63 }
64
65 /**
6f04e06c
EB
66 * "Existing file" constructor. Builds an attribute tree from a
67 * "mapping file" or mapping section previously saved somewhere.
8d1346f0 68 *
a52fde77
AM
69 * @param ss
70 * StateSystem to which this AT is attached
71 * @param fis
72 * File stream where to read the AT information. Make sure it's
6f04e06c 73 * sought at the right place!
a52fde77 74 * @throws IOException
a6917276 75 * If there is a problem reading from the file stream
a52fde77 76 */
a6917276 77 public AttributeTree(StateSystem ss, FileInputStream fis) throws IOException {
a52fde77 78 this(ss);
da66cc75 79 ObjectInputStream ois = new ObjectInputStream(new BufferedInputStream(fis));
a52fde77
AM
80
81 /* Read the header of the Attribute Tree file (or file section) */
da66cc75 82 int res = ois.readInt(); /* Magic number */
a52fde77 83 if (res != ATTRIB_TREE_MAGIC_NUMBER) {
da66cc75 84 throw new IOException("The attribute tree file section is either invalid or corrupted."); //$NON-NLS-1$
a52fde77
AM
85 }
86
a52fde77 87
da66cc75
AM
88 ArrayList<String[]> attribList;
89 try {
90 @SuppressWarnings("unchecked")
91 ArrayList<String[]> list = (ArrayList<String[]>) ois.readObject();
92 attribList = list;
93 } catch (ClassNotFoundException e) {
94 throw new IOException("Unrecognizable attribute list"); //$NON-NLS-1$
a52fde77
AM
95 }
96
97 /*
98 * Now we have 'list', the ArrayList of String arrays representing all
99 * the attributes. Simply create attributes the normal way from them.
100 */
da66cc75 101 for (String[] attrib : attribList) {
a52fde77
AM
102 this.getQuarkAndAdd(-1, attrib);
103 }
104 }
105
106 /**
a6917276 107 * Tell the Attribute Tree to write itself somewhere in a file.
8d1346f0 108 *
a6917276
AM
109 * @param file
110 * The file to write to
111 * @param pos
112 * The position (in bytes) in the file where to write
a52fde77 113 */
a69a9003 114 public synchronized void writeSelf(File file, long pos) {
da66cc75
AM
115 try (FileOutputStream fos = new FileOutputStream(file, true);
116 FileChannel fc = fos.getChannel();) {
117 fc.position(pos);
118 try (ObjectOutputStream oos = new ObjectOutputStream(fos)) {
119
120 /* Write the almost-magic number */
121 oos.writeInt(ATTRIB_TREE_MAGIC_NUMBER);
122
123 /* Compute the serialized list of attributes and write it */
124 List<String[]> list = new ArrayList<>(attributeList.size());
125 for (Attribute entry : this.attributeList) {
126 list.add(entry.getFullAttribute());
a52fde77 127 }
da66cc75 128 oos.writeObject(list);
a52fde77 129 }
a52fde77
AM
130 } catch (IOException e) {
131 e.printStackTrace();
132 }
da66cc75 133
a52fde77
AM
134 }
135
136 /**
137 * Return the number of attributes this system as seen so far. Note that
138 * this also equals the integer value (quark) the next added attribute will
139 * have.
8d1346f0 140 *
a6917276 141 * @return The current number of attributes in the tree
a52fde77 142 */
a69a9003 143 public synchronized int getNbAttributes() {
a52fde77
AM
144 return attributeList.size();
145 }
146
147 /**
a6917276
AM
148 * Get the quark for a given attribute path. No new attribute will be
149 * created : if the specified path does not exist, throw an error.
8d1346f0 150 *
a6917276
AM
151 * @param startingNodeQuark
152 * The quark of the attribute from which relative queries will
153 * start. Use '-1' to start at the root node.
154 * @param subPath
155 * The path to the attribute, relative to the starting node.
156 * @return The quark of the specified attribute
a52fde77 157 * @throws AttributeNotFoundException
a6917276 158 * If the specified path was not found
a52fde77 159 */
a69a9003 160 public synchronized int getQuarkDontAdd(int startingNodeQuark, String... subPath)
a52fde77 161 throws AttributeNotFoundException {
a52fde77
AM
162 assert (startingNodeQuark >= -1);
163
164 Attribute prevNode;
165
6abc2d88
AM
166 /* If subPath is empty, simply return the starting quark */
167 if (subPath == null || subPath.length == 0) {
168 return startingNodeQuark;
169 }
170
a52fde77
AM
171 /* Get the "starting node" */
172 if (startingNodeQuark == -1) {
173 prevNode = attributeTreeRoot;
174 } else {
175 prevNode = attributeList.get(startingNodeQuark);
176 }
177
178 int knownQuark = prevNode.getSubAttributeQuark(subPath);
179 if (knownQuark == -1) {
180 /*
181 * The attribute doesn't exist, but we have been specified to NOT
182 * add any new attributes.
183 */
e13bd4cd 184 throw new AttributeNotFoundException(ss.getSSID() + " Quark:" + startingNodeQuark + ", SubPath:" + Arrays.toString(subPath)); //$NON-NLS-1$ //$NON-NLS-2$
a52fde77
AM
185 }
186 /*
187 * The attribute was already existing, return the quark of that
188 * attribute
189 */
190 return knownQuark;
191 }
192
a6917276
AM
193 /**
194 * Get the quark of a given attribute path. If that specified path does not
195 * exist, it will be created (and the quark that was just created will be
196 * returned).
197 *
198 * @param startingNodeQuark
199 * The quark of the attribute from which relative queries will
200 * start. Use '-1' to start at the root node.
201 * @param subPath
202 * The path to the attribute, relative to the starting node.
203 * @return The quark of the attribute represented by the path
204 */
205 public synchronized int getQuarkAndAdd(int startingNodeQuark, String... subPath) {
206 // FIXME synchronized here is probably quite costly... maybe only locking
207 // the "for" would be enough?
a52fde77
AM
208 assert (subPath != null && subPath.length > 0);
209 assert (startingNodeQuark >= -1);
210
211 Attribute nextNode = null;
212 Attribute prevNode;
213
214 /* Get the "starting node" */
215 if (startingNodeQuark == -1) {
216 prevNode = attributeTreeRoot;
217 } else {
218 prevNode = attributeList.get(startingNodeQuark);
219 }
220
221 int knownQuark = prevNode.getSubAttributeQuark(subPath);
222 if (knownQuark == -1) {
223 /*
224 * The attribute was not in the table previously, and we want to add
225 * it
226 */
227 for (String curDirectory : subPath) {
228 nextNode = prevNode.getSubAttributeNode(curDirectory);
229 if (nextNode == null) {
230 /* This is where we need to start adding */
04927a83 231 nextNode = new Attribute(prevNode, checkNotNull(curDirectory), attributeList.size());
a52fde77
AM
232 prevNode.addSubAttribute(nextNode);
233 attributeList.add(nextNode);
8d1346f0 234 ss.addEmptyAttribute();
a52fde77
AM
235 }
236 prevNode = nextNode;
237 }
085a78a8 238 return attributeList.size() - 1;
a52fde77
AM
239 }
240 /*
241 * The attribute was already existing, return the quark of that
242 * attribute
243 */
244 return knownQuark;
245 }
246
0a9de3d2
AM
247 /**
248 * Returns the sub-attributes of the quark passed in parameter
8d1346f0 249 *
0a9de3d2 250 * @param attributeQuark
a6917276 251 * The quark of the attribute to print the sub-attributes of.
c66426fd 252 * @param recursive
a6917276
AM
253 * Should the query be recursive or not? If false, only children
254 * one level deep will be returned. If true, all descendants will
255 * be returned (depth-first search)
256 * @return The list of quarks representing the children attributes
0a9de3d2 257 * @throws AttributeNotFoundException
a6917276
AM
258 * If 'attributeQuark' is invalid, or if there is no attrbiute
259 * associated to it.
0a9de3d2 260 */
df2597e0 261 public synchronized @NonNull List<@NonNull Integer> getSubAttributes(int attributeQuark, boolean recursive)
0a9de3d2 262 throws AttributeNotFoundException {
df2597e0 263 List<@NonNull Integer> listOfChildren = new ArrayList<>();
0a9de3d2 264 Attribute startingAttribute;
c66426fd 265
0a9de3d2 266 /* Check if the quark is valid */
f94a0bac 267 if (attributeQuark < -1 || attributeQuark >= attributeList.size()) {
e13bd4cd 268 throw new AttributeNotFoundException(ss.getSSID() + " Quark:" + attributeQuark); //$NON-NLS-1$
0a9de3d2 269 }
c66426fd 270
0a9de3d2 271 /* Set up the node from which we'll start the search */
c66426fd 272 if (attributeQuark == -1) {
0a9de3d2
AM
273 startingAttribute = attributeTreeRoot;
274 } else {
275 startingAttribute = attributeList.get(attributeQuark);
276 }
c66426fd 277
0a9de3d2 278 /* Iterate through the sub-attributes and add them to the list */
c66426fd 279 addSubAttributes(listOfChildren, startingAttribute, recursive);
0a9de3d2 280
a52fde77
AM
281 return listOfChildren;
282 }
283
0fdd2c45
FG
284 /**
285 * Returns the parent quark of the attribute. The root attribute has no
286 * parent and will return <code>-1</code>
287 *
288 * @param quark
289 * The quark of the attribute
290 * @return Quark of the parent attribute or <code>-1</code> for the root
291 * attribute
292 */
a69a9003 293 public synchronized int getParentAttributeQuark(int quark) {
0fdd2c45
FG
294 if (quark == -1) {
295 return quark;
296 }
297 return attributeList.get(quark).getParentAttributeQuark();
298 }
299
c66426fd
AM
300 private void addSubAttributes(List<Integer> list, Attribute curAttribute,
301 boolean recursive) {
cb42195c 302 for (Attribute childNode : curAttribute.getSubAttributes()) {
c66426fd
AM
303 list.add(childNode.getQuark());
304 if (recursive) {
305 addSubAttributes(list, childNode, true);
306 }
307 }
308 }
309
a6917276
AM
310 /**
311 * Get then base name of an attribute specified by a quark.
312 *
313 * @param quark
314 * The quark of the attribute
315 * @return The (base) name of the attribute
316 */
a69a9003 317 public synchronized @NonNull String getAttributeName(int quark) {
50678114
AM
318 return attributeList.get(quark).getName();
319 }
320
a6917276
AM
321 /**
322 * Get the full path name of an attribute specified by a quark.
323 *
324 * @param quark
325 * The quark of the attribute
326 * @return The full path name of the attribute
327 */
a69a9003 328 public synchronized @NonNull String getFullAttributeName(int quark) {
a52fde77
AM
329 return attributeList.get(quark).getFullAttributeName();
330 }
331
34638411
AM
332 /**
333 * Get the full path name (as an array of path elements) of an attribute
334 * specified by a quark.
335 *
336 * @param quark
337 * The quark of the attribute
338 * @return The path elements of the full path
339 */
4c4e2816 340 public synchronized String @NonNull [] getFullAttributePathArray(int quark) {
34638411
AM
341 return attributeList.get(quark).getFullAttribute();
342 }
343
a6917276
AM
344 /**
345 * Debug-print all the attributes in the tree.
346 *
347 * @param writer
348 * The writer where to print the output
349 */
a69a9003 350 public synchronized void debugPrint(PrintWriter writer) {
a52fde77
AM
351 attributeTreeRoot.debugPrint(writer);
352 }
353
a6917276 354}
This page took 0.102438 seconds and 5 git commands to generate.