1 /*******************************************************************************
2 * Copyright (c) 2014 École Polytechnique de Montréal
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
10 * Florian Wininger - Initial API and implementation
11 *******************************************************************************/
13 package org
.eclipse
.linuxtools
.tmf
.analysis
.xml
.core
.stateprovider
;
16 import java
.io
.IOException
;
17 import java
.util
.Collections
;
18 import java
.util
.HashMap
;
19 import java
.util
.HashSet
;
23 import javax
.xml
.parsers
.DocumentBuilder
;
24 import javax
.xml
.parsers
.DocumentBuilderFactory
;
25 import javax
.xml
.parsers
.ParserConfigurationException
;
27 import org
.eclipse
.core
.runtime
.IPath
;
28 import org
.eclipse
.linuxtools
.internal
.tmf
.analysis
.xml
.core
.Activator
;
29 import org
.eclipse
.linuxtools
.internal
.tmf
.analysis
.xml
.core
.stateprovider
.model
.TmfXmlEventHandler
;
30 import org
.eclipse
.linuxtools
.internal
.tmf
.analysis
.xml
.core
.stateprovider
.model
.TmfXmlLocation
;
31 import org
.eclipse
.linuxtools
.tmf
.analysis
.xml
.core
.module
.Messages
;
32 import org
.eclipse
.linuxtools
.tmf
.core
.event
.ITmfEvent
;
33 import org
.eclipse
.linuxtools
.tmf
.core
.statesystem
.AbstractTmfStateProvider
;
34 import org
.eclipse
.linuxtools
.tmf
.core
.statesystem
.ITmfStateSystemBuilder
;
35 import org
.eclipse
.linuxtools
.tmf
.core
.trace
.ITmfTrace
;
36 import org
.eclipse
.osgi
.util
.NLS
;
37 import org
.w3c
.dom
.Document
;
38 import org
.w3c
.dom
.Element
;
39 import org
.w3c
.dom
.Node
;
40 import org
.w3c
.dom
.NodeList
;
41 import org
.xml
.sax
.SAXException
;
44 * This is the state change input plug-in for TMF's state system which handles
47 * @author Florian Wininger
49 public class XmlStateProvider
extends AbstractTmfStateProvider
{
51 /** Root quark, to get values at the root of the state system */
52 public static final int ROOT_QUARK
= -1;
54 * Error quark, value taken when a state system quark query is in error.
56 * FIXME: Originally in the code, the -1 was used for both root quark and
57 * return errors, so it has the same value as root quark, but maybe it can
58 * be changed to something else -2? A quark can never be negative
60 public static final int ERROR_QUARK
= -1;
62 private final IPath fFilePath
;
63 private final String fStateId
;
65 /** List of all Event Handlers */
66 private final Set
<TmfXmlEventHandler
> fEventHandlers
= new HashSet
<>();
68 /** List of all Locations */
69 private final Set
<TmfXmlLocation
> fLocations
;
71 /** Map for defined values */
72 private final Map
<String
, String
> fDefinedValues
= new HashMap
<>();
74 // ------------------------------------------------------------------------
76 // ------------------------------------------------------------------------
79 * Instantiate a new state provider plug-in.
84 * The state system id, corresponding to the analysis_id
85 * attribute of the state provider element of the XML file
87 * Path to the XML file containing the state provider definition
89 public XmlStateProvider(ITmfTrace trace
, String stateid
, IPath file
) {
90 super(trace
, ITmfEvent
.class, stateid
);
93 Element doc
= loadXMLNode();
95 fLocations
= new HashSet
<>();
99 /* parser for defined Values */
100 NodeList definedStateNodes
= doc
.getElementsByTagName(TmfXmlStrings
.DEFINED_VALUE
);
101 for (int i
= 0; i
< definedStateNodes
.getLength(); i
++) {
102 Element element
= (Element
) definedStateNodes
.item(i
);
103 fDefinedValues
.put(element
.getAttribute(TmfXmlStrings
.NAME
), element
.getAttribute(TmfXmlStrings
.VALUE
));
106 /* parser for the locations */
107 NodeList locationNodes
= doc
.getElementsByTagName(TmfXmlStrings
.LOCATION
);
108 Set
<TmfXmlLocation
> locations
= new HashSet
<>();
109 for (int i
= 0; i
< locationNodes
.getLength(); i
++) {
110 Element element
= (Element
) locationNodes
.item(i
);
111 TmfXmlLocation location
= new TmfXmlLocation(element
, this);
112 locations
.add(location
);
114 fLocations
= Collections
.unmodifiableSet(locations
);
116 /* parser for the event handlers */
117 NodeList nodes
= doc
.getElementsByTagName(TmfXmlStrings
.EVENT_HANDLER
);
118 for (int i
= 0; i
< nodes
.getLength(); i
++) {
119 Element element
= (Element
) nodes
.item(i
);
120 TmfXmlEventHandler handler
= new TmfXmlEventHandler(element
, this);
121 fEventHandlers
.add(handler
);
126 * Get the state id of the state provider
128 * @return The state id of the state provider
130 public String
getStateId() {
134 // ------------------------------------------------------------------------
136 // ------------------------------------------------------------------------
139 public int getVersion() {
140 Node ssNode
= loadXMLNode();
141 if (ssNode
instanceof Element
) {
142 Element element
= (Element
) ssNode
;
143 return Integer
.valueOf(element
.getAttribute(TmfXmlStrings
.VERSION
));
146 * The version attribute is mandatory and XML files that don't validate
147 * with the XSD are ignored, so this should never happen
149 throw new IllegalStateException("The state provider XML node should have a version attribute"); //$NON-NLS-1$
153 public XmlStateProvider
getNewInstance() {
154 return new XmlStateProvider(this.getTrace(), getStateId(), fFilePath
);
158 protected void eventHandle(ITmfEvent event
) {
162 for (TmfXmlEventHandler eventHandler
: fEventHandlers
) {
163 eventHandler
.handleEvent(event
);
168 public ITmfStateSystemBuilder
getAssignedStateSystem() {
172 // ------------------------------------------------------------------------
174 // ------------------------------------------------------------------------
177 * Loads the XML file and returns the element at the root of the current
180 * @return The XML node at the root of the state provider
182 private Element
loadXMLNode() {
185 File XMLFile
= fFilePath
.toFile();
186 if (XMLFile
== null || !XMLFile
.exists() || !XMLFile
.isFile()) {
190 /* Load the XML File */
191 DocumentBuilderFactory dbFactory
= DocumentBuilderFactory
.newInstance();
192 DocumentBuilder dBuilder
;
194 dBuilder
= dbFactory
.newDocumentBuilder();
195 Document doc
= dBuilder
.parse(XMLFile
);
196 doc
.getDocumentElement().normalize();
198 /* get the state providers and find the corresponding one */
199 NodeList stateproviderNodes
= doc
.getElementsByTagName(TmfXmlStrings
.STATE_PROVIDER
);
200 Element stateproviderNode
= null;
202 for (int i
= 0; i
< stateproviderNodes
.getLength(); i
++) {
203 Element node
= (Element
) stateproviderNodes
.item(i
);
204 String analysisid
= node
.getAttribute(TmfXmlStrings
.ANALYSIS_ID
);
205 if (analysisid
.equals(fStateId
)) {
206 stateproviderNode
= node
;
210 return stateproviderNode
;
211 } catch (ParserConfigurationException
| IOException e
) {
212 Activator
.logError("Error loading XML file", e
); //$NON-NLS-1$
213 } catch (SAXException e
) {
214 Activator
.logError(NLS
.bind(Messages
.XmlUtils_XmlValidationError
, e
.getLocalizedMessage()), e
);
221 * Get the list of locations defined in this state provider
223 * @return The list of {@link TmfXmlLocation}
225 public Iterable
<TmfXmlLocation
> getLocations() {
230 * Get the defined value associated with a constant
233 * The constant defining this value
234 * @return The actual value corresponding to this constant
236 public String
getDefinedValue(String constant
) {
237 return fDefinedValues
.get(constant
);
241 * Get the requested value for an attribute. If the value is a pre-defined
242 * value, we return the string corresponding in the defined values map.
246 * @return the actual string value
248 public String
getAttributeValue(String name
) {
249 String attribute
= name
;
250 if (attribute
.startsWith(TmfXmlStrings
.VARIABLE_PREFIX
)) {
251 /* search the attribute in the map without the fist character $ */
252 attribute
= getDefinedValue(attribute
.substring(1));