| 1 | /******************************************************************************* |
| 2 | * Copyright (c) 2014 École Polytechnique de Montréal |
| 3 | * |
| 4 | * All rights reserved. This program and the accompanying materials are |
| 5 | * made available under the terms of the Eclipse Public License v1.0 which |
| 6 | * accompanies this distribution, and is available at |
| 7 | * http://www.eclipse.org/legal/epl-v10.html |
| 8 | * |
| 9 | * Contributors: |
| 10 | * Florian Wininger - Initial API and implementation |
| 11 | * Geneviève Bastien - Review of the initial implementation |
| 12 | *******************************************************************************/ |
| 13 | |
| 14 | package org.eclipse.linuxtools.tmf.analysis.xml.ui.views.timegraph; |
| 15 | |
| 16 | import java.util.Collections; |
| 17 | import java.util.List; |
| 18 | |
| 19 | import org.eclipse.jdt.annotation.NonNull; |
| 20 | import org.eclipse.linuxtools.internal.tmf.analysis.xml.ui.TmfXmlUiStrings; |
| 21 | import org.eclipse.linuxtools.tmf.analysis.xml.core.model.ITmfXmlModelFactory; |
| 22 | import org.eclipse.linuxtools.tmf.analysis.xml.core.model.ITmfXmlStateAttribute; |
| 23 | import org.eclipse.linuxtools.tmf.analysis.xml.core.model.TmfXmlLocation; |
| 24 | import org.eclipse.linuxtools.tmf.analysis.xml.core.model.readonly.TmfXmlReadOnlyModelFactory; |
| 25 | import org.eclipse.linuxtools.tmf.analysis.xml.core.module.IXmlStateSystemContainer; |
| 26 | import org.eclipse.linuxtools.tmf.analysis.xml.core.module.XmlUtils; |
| 27 | import org.eclipse.linuxtools.tmf.core.exceptions.AttributeNotFoundException; |
| 28 | import org.eclipse.linuxtools.tmf.core.exceptions.StateSystemDisposedException; |
| 29 | import org.eclipse.linuxtools.tmf.core.interval.ITmfStateInterval; |
| 30 | import org.eclipse.linuxtools.tmf.core.statesystem.ITmfStateSystem; |
| 31 | import org.eclipse.linuxtools.tmf.core.trace.ITmfTrace; |
| 32 | import org.eclipse.linuxtools.tmf.ui.widgets.timegraph.model.TimeGraphEntry; |
| 33 | import org.w3c.dom.Element; |
| 34 | |
| 35 | /** |
| 36 | * An XML-defined entry, or row, to display in the XML state system view |
| 37 | * |
| 38 | * @author Florian Wininger |
| 39 | */ |
| 40 | public class XmlEntry extends TimeGraphEntry implements IXmlStateSystemContainer { |
| 41 | |
| 42 | private static final String EMPTY_STRING = ""; //$NON-NLS-1$ |
| 43 | |
| 44 | /** Type of resource */ |
| 45 | public static enum EntryDisplayType { |
| 46 | /** Entries without events to display (filler rows, etc.) */ |
| 47 | NULL, |
| 48 | /** Entries with time events */ |
| 49 | DISPLAY |
| 50 | } |
| 51 | |
| 52 | private final ITmfTrace fTrace; |
| 53 | private final EntryDisplayType fType; |
| 54 | private final int fBaseQuark; |
| 55 | private final int fDisplayQuark; |
| 56 | private final String fParentId; |
| 57 | private final String fId; |
| 58 | private final @NonNull ITmfStateSystem fSs; |
| 59 | private final Element fElement; |
| 60 | |
| 61 | /** |
| 62 | * Constructor |
| 63 | * |
| 64 | * @param baseQuark |
| 65 | * The quark matching this entry, or <code>-1</code> if no quark |
| 66 | * @param displayQuark |
| 67 | * The quark containing the value to display. It was needed by |
| 68 | * the caller to get the start and end time of this entry, so we |
| 69 | * receive it as parameter from him. |
| 70 | * @param trace |
| 71 | * The trace on which we are working (FIXME: is this parameter |
| 72 | * useful?) |
| 73 | * @param name |
| 74 | * The name of this entry. It will be overridden if a "name" XML |
| 75 | * tag is specified in the entryElement. It will also be used as |
| 76 | * the ID of this entry if no "id" XML tag is specified. It |
| 77 | * typically is the attribute name corresponding the the base |
| 78 | * quark. |
| 79 | * @param startTime |
| 80 | * The start time of this entry lifetime |
| 81 | * @param endTime |
| 82 | * The end time of this entry |
| 83 | * @param type |
| 84 | * The display type of this entry |
| 85 | * @param ss |
| 86 | * The state system this entry belongs to |
| 87 | * @param entryElement |
| 88 | * The XML element describing this entry. This element will be |
| 89 | * used to determine, if available, the parent, ID, name and |
| 90 | * other display option of this entry |
| 91 | */ |
| 92 | public XmlEntry(int baseQuark, int displayQuark, ITmfTrace trace, String name, long startTime, long endTime, EntryDisplayType type, @NonNull ITmfStateSystem ss, Element entryElement) { |
| 93 | super(name, startTime, endTime); |
| 94 | fTrace = trace; |
| 95 | fType = type; |
| 96 | fBaseQuark = baseQuark; |
| 97 | fDisplayQuark = displayQuark; |
| 98 | fSs = ss; |
| 99 | fElement = entryElement; |
| 100 | |
| 101 | /* Get the parent if specified */ |
| 102 | List<Element> elements = XmlUtils.getChildElements(fElement, TmfXmlUiStrings.PARENT_ELEMENT); |
| 103 | if (elements.size() > 0) { |
| 104 | fParentId = getFirstValue(elements.get(0)); |
| 105 | } else { |
| 106 | fParentId = EMPTY_STRING; |
| 107 | } |
| 108 | |
| 109 | /* Get the name of this entry */ |
| 110 | elements = XmlUtils.getChildElements(fElement, TmfXmlUiStrings.NAME_ELEMENT); |
| 111 | if (elements.size() > 0) { |
| 112 | String nameFromSs = getFirstValue(elements.get(0)); |
| 113 | if (!nameFromSs.isEmpty()) { |
| 114 | setName(nameFromSs); |
| 115 | } |
| 116 | } |
| 117 | |
| 118 | /* Get the id of this entry */ |
| 119 | elements = XmlUtils.getChildElements(fElement, TmfXmlUiStrings.ID_ELEMENT); |
| 120 | if (elements.size() > 0) { |
| 121 | fId = getFirstValue(elements.get(0)); |
| 122 | } else { |
| 123 | fId = name; |
| 124 | } |
| 125 | |
| 126 | } |
| 127 | |
| 128 | /** |
| 129 | * Constructor |
| 130 | * |
| 131 | * @param baseQuark |
| 132 | * The quark matching this entry, or <code>-1</code> if no quark |
| 133 | * @param trace |
| 134 | * The trace on which we are working |
| 135 | * @param name |
| 136 | * The exec_name of this entry |
| 137 | * @param ss |
| 138 | * The state system this entry belongs to |
| 139 | */ |
| 140 | public XmlEntry(int baseQuark, ITmfTrace trace, String name, @NonNull ITmfStateSystem ss) { |
| 141 | super(name, ss.getStartTime(), ss.getCurrentEndTime()); |
| 142 | fTrace = trace; |
| 143 | fType = EntryDisplayType.NULL; |
| 144 | fBaseQuark = baseQuark; |
| 145 | fDisplayQuark = baseQuark; |
| 146 | fSs = ss; |
| 147 | fElement = null; |
| 148 | fParentId = EMPTY_STRING; |
| 149 | fId = name; |
| 150 | } |
| 151 | |
| 152 | /** Return the state value of the first interval with a non-null value */ |
| 153 | private String getFirstValue(Element stateAttribute) { |
| 154 | ITmfXmlModelFactory factory = TmfXmlReadOnlyModelFactory.getInstance(); |
| 155 | ITmfXmlStateAttribute display = factory.createStateAttribute(stateAttribute, this); |
| 156 | int quark = display.getAttributeQuark(fBaseQuark); |
| 157 | if (quark != IXmlStateSystemContainer.ERROR_QUARK) { |
| 158 | try { |
| 159 | /* Find the first attribute with a parent */ |
| 160 | List<ITmfStateInterval> execNameIntervals = fSs.queryHistoryRange(quark, getStartTime(), getEndTime()); |
| 161 | for (ITmfStateInterval execNameInterval : execNameIntervals) { |
| 162 | |
| 163 | if (!execNameInterval.getStateValue().isNull()) { |
| 164 | return execNameInterval.getStateValue().toString(); |
| 165 | } |
| 166 | } |
| 167 | } catch (AttributeNotFoundException | StateSystemDisposedException e) { |
| 168 | } |
| 169 | } |
| 170 | return EMPTY_STRING; |
| 171 | } |
| 172 | |
| 173 | /** |
| 174 | * Get the trace this entry was taken from |
| 175 | * |
| 176 | * @return the entry's trace |
| 177 | */ |
| 178 | public ITmfTrace getTrace() { |
| 179 | return fTrace; |
| 180 | } |
| 181 | |
| 182 | /** |
| 183 | * Get the entry Type of this entry. Uses the inner EntryDisplayType enum. |
| 184 | * |
| 185 | * @return The entry type |
| 186 | */ |
| 187 | public EntryDisplayType getType() { |
| 188 | return fType; |
| 189 | } |
| 190 | |
| 191 | /** |
| 192 | * Get the quark from which to get the time event intervals for this entry. |
| 193 | * |
| 194 | * @return The attribute quark containing the intervals to display |
| 195 | */ |
| 196 | public int getDisplayQuark() { |
| 197 | return fDisplayQuark; |
| 198 | } |
| 199 | |
| 200 | /** |
| 201 | * Get this entry's ID |
| 202 | * |
| 203 | * @return The id of the entry. |
| 204 | */ |
| 205 | public String getId() { |
| 206 | return fId; |
| 207 | } |
| 208 | |
| 209 | /** |
| 210 | * Return the entry's parent ID. It corresponds to another entry's ID |
| 211 | * received from the {@link #getId()} method. |
| 212 | * |
| 213 | * @return The parent ID of this entry |
| 214 | */ |
| 215 | public String getParentId() { |
| 216 | return fParentId; |
| 217 | } |
| 218 | |
| 219 | @Override |
| 220 | public boolean hasTimeEvents() { |
| 221 | if (fType == EntryDisplayType.NULL) { |
| 222 | return false; |
| 223 | } |
| 224 | return true; |
| 225 | } |
| 226 | |
| 227 | /** |
| 228 | * Add a child to this entry of type XmlEntry |
| 229 | * |
| 230 | * @param entry |
| 231 | * The entry to add |
| 232 | */ |
| 233 | public void addChild(XmlEntry entry) { |
| 234 | int index; |
| 235 | for (index = 0; index < getChildren().size(); index++) { |
| 236 | XmlEntry other = (XmlEntry) getChildren().get(index); |
| 237 | if (entry.getType().compareTo(other.getType()) < 0) { |
| 238 | break; |
| 239 | } else if (entry.getType().equals(other.getType())) { |
| 240 | if (entry.getName().compareTo(other.getName()) < 0) { |
| 241 | break; |
| 242 | } |
| 243 | } |
| 244 | } |
| 245 | |
| 246 | entry.setParent(this); |
| 247 | getChildren().add(index, entry); |
| 248 | } |
| 249 | |
| 250 | /** |
| 251 | * Return the state system this entry is associated to |
| 252 | * |
| 253 | * @return The state system, or <code>null</code> if the state system can't |
| 254 | * be found. |
| 255 | */ |
| 256 | @Override |
| 257 | @NonNull |
| 258 | public ITmfStateSystem getStateSystem() { |
| 259 | return fSs; |
| 260 | } |
| 261 | |
| 262 | @Override |
| 263 | public String getAttributeValue(String name) { |
| 264 | return name; |
| 265 | } |
| 266 | |
| 267 | @Override |
| 268 | public Iterable<TmfXmlLocation> getLocations() { |
| 269 | return Collections.EMPTY_SET; |
| 270 | } |
| 271 | |
| 272 | } |